diff --git a/.gitignore b/.gitignore index 6e34e09..e69de29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +0,0 @@ -News_/ -News.chyrp.old/ -donate/config.php -donate/insert-value.sh -paste/raw/* -repo/* diff --git a/.htaccess b/.htaccess index fd669af..a3a8b6f 100644 --- a/.htaccess +++ b/.htaccess @@ -1,31 +1,2 @@ -Options -Indexes - -Redirect 301 /cadence http://kxstudio.linuxaudio.org/Applications:Cadence -Redirect 301 /cadence-jackmeter http://kxstudio.linuxaudio.org/Applications:Cadence-JackMeter -Redirect 301 /cadence-jacksettings http://kxstudio.linuxaudio.org/Applications:Cadence-JackSettings -Redirect 301 /cadence-logs http://kxstudio.linuxaudio.org/Applications:Cadence-Logs -Redirect 301 /cadence-render http://kxstudio.linuxaudio.org/Applications:Cadence-Render -Redirect 301 /cadence-xycontroller http://kxstudio.linuxaudio.org/Applications:Cadence-XYController -Redirect 301 /catarina http://kxstudio.linuxaudio.org/Applications:Catarina -Redirect 301 /catia http://kxstudio.linuxaudio.org/Applications:Catia -Redirect 301 /claudia http://kxstudio.linuxaudio.org/Applications:Claudia -Redirect 301 /claudia-launcher http://kxstudio.linuxaudio.org/Applications:Claudia-Launcher -Redirect 301 /carla http://kxstudio.linuxaudio.org/Applications:Carla -Redirect 301 /carla-control http://kxstudio.linuxaudio.org/Applications:Carla-Control - -Redirect 301 /applications http://kxstudio.linuxaudio.org/Applications -Redirect 301 /documentation http://kxstudio.linuxaudio.org/Documentation -Redirect 301 /donations http://kxstudio.linuxaudio.org/Donations -Redirect 301 /downloads http://kxstudio.linuxaudio.org/Downloads -Redirect 301 /news http://kxstudio.linuxaudio.org/News -Redirect 301 /plugins http://kxstudio.linuxaudio.org/Plugins -Redirect 301 /repositories http://kxstudio.linuxaudio.org/Repositories - -RedirectMatch 301 ^/KXStudio:(.*)$ /$1 -RedirectMatch 301 ^/Documentation:Ubuntu:(.*)$ /Documentation:Repository:$1 - RewriteEngine On -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteCond %{REQUEST_FILENAME}\.php -f -RewriteRule ^(.*)$ $1.php [L,QSA] +RewriteRule (.*) https://kx.studio/$1 [L,R=301] diff --git a/Applications.php b/Applications.php deleted file mode 100644 index 2204ae2..0000000 --- a/Applications.php +++ /dev/null @@ -1,330 +0,0 @@ - - - - -
-

- This section lists the applications made by the KXStudio Team.
- All applications are open-source and completely free. -

-

- You might also want to check: -

- -
-
- - - -
-

- cadence -

-

- - - - -

-
-

- - Cadence
- Cadence is a set of tools useful for audio production.
- This is the main app. It performs system checks, manages JACK, calls other tools and make system tweaks.
- (Most of the tools below are part of the Cadence suite). -


-

-
- - - -
-

- cadence-jackmeter

-

- - - - - - -

-
-

- - Cadence-JackMeter
- Cadence-JackMeter is a digital peak meter for JACK.
- It automatically connects itself to all application JACK output ports that are also connected to the system output.
-
-

-
- - - -
-

- cadence-jacksettings

-

- - - - -

-
-

- - Cadence-JackSettings
- Cadence-JackSettings is a simple and easy-to-use configure dialog for jackdbus.
- It can configure JACK's driver and engine parameters, and it also supports LADISH studios.
-
-

-
- - - -
-

- cadence-logs

-

- - - - -

-
-

- - Cadence-Logs
- Cadence-Logs is a small tool that shows JACK, A2J, LASH and LADISH logs in a multi-tab window.
- This is very similar to the the 'ladilog' app but here the logs are viewed in a text box, making it easy to browse and extract status messages using copy and paste commands.
-
-

-
- - - -
-

- cadence-render

-

- - - - -

-
-

- - Cadence-Render
- Cadence-Render is a tool to record (or 'render') a JACK project using jack-capture, controlled by JACK Transport.
- It supports a vast number of file types and can render in both realtime and freewheel modes.
-
-

-
- - - -
-

- cadence-xycontroller

-

- - - - - - -

-
-

- - Cadence-XY Controller
- Cadence-XY Controller is a simple XY widget that sends and receives data from Jack MIDI.
- It can send data through specific channels and has a MIDI Keyboard too.
-

-

-
- - - -
-

- catarina

-

- - - - - - -

-
-

- - Catarina
- Catarina is a Patchbay test app, created while the PatchCanvas module was being developed.
- It allows the user to experiment with the patchbay, without using ALSA, JACK or LADISH.
- You can save & load patchbay configurations too.
-
-

-
- - - -
-

- catia

-

- - - - - - -

-
-

- - Catia
- Catia is a JACK Patchbay, with some neat features like A2J bridge support and JACK Transport.
- It's supposed to be as simple as possible (there's - Claudia for advanced things), - so it can work nicely on non-Linux platforms.
-
-
-

-
- - - -
-

- claudia

-

- - - - -

-
-

- - Claudia
- Claudia is a LADISH frontend; it's just like Catia, but focused at session management through LADISH.
- It has a bit more features than the official LADISH GUI, with a nice preview of the main canvas in the bottom-left.
- It also implements the 'Claudia-Launcher' add-application style for LADISH.
-
-

-
- - - -
-

- claudia-launcher

-

- - - -

-
-

- - Claudia-Launcher
- Claudia-Launcher is a multimedia application launcher with LADISH support.
- It searches for installed packages (not binaries), and displays the respective content as a launcher.
- The content is got through an hardcoded database, created and/or modified to suit the target distribution.
-
-

-
- - - -
-

- carla

-

- - - - - - -

-
-

- - Carla
- Carla is an audio plugin host, with support for many audio drivers and plugin formats.
- It has some nice features like automation of parameters via MIDI CC and full OSC control.
- Currently supports LADSPA, DSSI, LV2, VST2/3 and AU plugin formats, plus GIG, SF2 and SFZ sounds banks.
-
-

-
- - - -
-

- carla-control

-

- - - - - -

-
-

- - Carla-Control
- TODO.
-
-

-
- -
- -
What do those little icons mean?
- - - - - - - - - - - - - - - - - - - - - -
- Supports ArchLinux (Available in AUR)
- Supports Debian (Available at the KXStudio Repositories)
- Supports Ubuntu (Available at the KXStudio Repositories)
- Supports all GNU/Linux systems in general (Binaries and Source Code available in the Downloads page)
- Supports Mac OS (Package available in the Downloads page)
- Supports Windows (Binaries available in the Downloads page)
- -
- -

- - diff --git a/Applications:Cadence-JackMeter.php b/Applications:Cadence-JackMeter.php deleted file mode 100644 index bb181c5..0000000 --- a/Applications:Cadence-JackMeter.php +++ /dev/null @@ -1,84 +0,0 @@ - - - -

- Cadence-JackMeter is a digital peak meter for JACK.
- It automatically connects itself to all application JACK output ports that are also connected to the system output. -

-

- This tool can be executed as 'cadence-jackmeter' for monitoring outputs or 'cadence-jackmeter -in' for monitoring inputs. -

- - -

The Interface

-

- A screenshot follows:
- cadence-jackmeter.png -

-

- This is a regular digital-audio peak meter as you probably have seen many times before.
- Note that the peak values are based on programming data (0.0 <-> 1.0) and not dB. -

-

- The meter has small lines to guide you. The value of these lines are (from bottom to top): -

- - - -

Usage

-

- Simply run it and it will automatically connect to all JACK audio ports currently outputting sound to the 'system' client (or inputs if using '-in' argument).
- The JACK client name is 'M' for "meter". When you change connections in the JACK graph, Cadence-JackMeter will change accordingly. -

- - -

Download

-

- Cadence-JackMeter is available in the KXStudio repositories and ArchLinux AUR ('cadence-tools' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux and Windows (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
- - - Windows 32bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Cadence-JackSettings.php b/Applications:Cadence-JackSettings.php deleted file mode 100644 index a596070..0000000 --- a/Applications:Cadence-JackSettings.php +++ /dev/null @@ -1,93 +0,0 @@ - - - -

- Cadence-JackSettings is a simple and easy-to-use configure dialog for jackdbus (either JACK2 or JACK1 + DBus patch).
- It can configure JACK's driver and engine parameters (network not yet implemented), and it also supports LADISH studios. -

-

- This tool can be executed as 'cadence_jacksettings' or from within Cadence, - Catia and Claudia. -

- - -

The Interface

-

- A screenshot of the first, "Engine" tab:
- cadence-jacksettings1.png -

-

- A screenshot of the second, "Driver" tab:
- cadence-jacksettings2.png -

-

- The third tab, "Network", is not implemented yet. -

-

- You probably recognize some options from other JACK configure tools such as QjackCtl.
- They are similar because they manage the same thing (JACK). The difference is mostly at the layout level — that is, how things are organized in the GUI. -

-

- Most options have a tooltip to help. The 'driver' option (table on the left in the 2nd screenshot) will trigger small changes on the layout.
- NOTE: Leaving a particular driver selected after closing the tool will result in that driver being used the next time JACK starts. -

- - -

Usage

-

- The options will be available (or not) according to your JACK version.
- JACK1 and JACK2 options are different, so Cadence-JackSettings interface will change for them. Some set-ups might also have LADISH specific options.
- (For this first release Cadence-JackSettings is targeted at JACK2 and some minor JACK1 options will be missing). -

-

- If you want a more in-depth explanation of what each option does, you can checkout your 'jackd' manual page or view it online here.
- The first part of that manual relates to the 'Engine' options, then specific driver ones.
- Remember that Cadence-JackSettings doesn't really uses 'jackd', but since we are both targeting JACK the options are the same. -

-

- NOTE: The settings are shared across jackdbus-capable applications (jack_control and ladiconf), but not QjackCtl.
- QjackCtl doesn't support querying and storing settings via jackdbus (it uses its own internal settings), so any change in it will not affect Cadence-JackSettings and vice-versa.
- We recommend using only Cadence and avoid (or uninstall) QjackCtl. -

- - -

Download

-

- Cadence-JackSettings is available in the KXStudio repositories and ArchLinux AUR ('cadence-tools' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Cadence-Logs.php b/Applications:Cadence-Logs.php deleted file mode 100644 index d920e99..0000000 --- a/Applications:Cadence-Logs.php +++ /dev/null @@ -1,82 +0,0 @@ - - - -

- Cadence-Logs is a small tool that shows JACK, A2J, LASH and LADISH logs in a multi-tab window.
- This is very similar to the the 'ladilog' app but here the logs are viewed in a text box, making it easy to browse and extract status messages using copy and paste commands. -

-

- This tool can be executed as 'cadence_logs' or within Catia and - Claudia from their 'Tools' menu. -

- - -

The Interface

-

- A screenshot follows, showing the JACK log:
- cadence-logs.png -

-

- It couldn't be simpler: 4 tabs for the different logs and 2 buttons.
- Each tab shows the log for the application indicated in the tab name. If a log does not exist, its tab will not be shown.
- (As you can see in the screen-shot above the 'LASH' tab is missing, indicating that its log does not exist in the system). -

-

- The 'Close' button will, obviously, close the tool window.
- The 'Purge all logs' button will empty all the available logs (it will not delete the files, but overwrite them). If a log file does not exist it will not be created. -

- - -

Usage

-

- This is a very small tool with a very small purpose: to quickly view the audio-related logs and allow you to copy&paste from them.
- The logs are actually files that exist within your home folder. The full filenames for each log are:
-

- - - -

Download

-

- Cadence-Logs is available in the KXStudio repositories and ArchLinux AUR ('cadence-tools' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Cadence-Render.php b/Applications:Cadence-Render.php deleted file mode 100644 index c721c20..0000000 --- a/Applications:Cadence-Render.php +++ /dev/null @@ -1,111 +0,0 @@ - - - -

- Cadence-Render is a tool to record (or 'render') a JACK project using jack-capture, controlled by JACK Transport.
- It supports a vast number of file types and can render in both realtime and freewheel modes.
-

-

- This tool can be executed as 'cadence_render' or within Catia and - Claudia from their 'Tools' menu.
- The minimum required version of jack-capture is 0.9.60. If jack-capture is not found in $PATH, Cadence-Render will refuse to run. -

- - -

The Interface

-

- A screenshot follows:
- cadence-render.png -

-

- You have two render modes: Realtime and Freewheel (more on that below).
- The Start and End Time specifies what part of the JACK project to record. The "now" buttons will change their values to the current JACK Transport location.
- Which encoding formats are available will depend on your current jack-capture version. Newer versions should support more formats. mp3 is not an option for the time being.
-

-

- When recording, the 'Render' button will change to 'Stop', and the progress bar will slowly fill indicating how much percentage of the project has been rendered so far.
- The rest of the interface is pretty straight forward. -

- - -

Usage

-

- Cadence-Render uses jack-capture to do the actual recording in the background.
- When 'Render' is pressed it will change the JACK buffer-size first (if modified), relocate Transport to the position specified in "Start Time" and then start recording.
- The recording will automatically stop when JACK Transport reaches the time set in "End Time". If the buffer-size was changed, it will be changed back.
- This makes it particularly useful to render projects in freewheel mode with apps that don't support it directly. -

-

- Changing the buffer size before recording might be useful if you use plugin automation in hosts that don't support per-sample automation.
- The way this works is that a plugin process() call is only called once per JACK callback and thus a plugin parameter will have low precision.
- Having a lower buffer size means the host will have to call process() more often (thus increasing precision), but at a cost of higher CPU usage.
- But note that, if the host or plugin takes too much time in the JACK callback, the audio buffer will not be filled properly and you'll most likely hear "cracks" (aka xruns). - Freewheel mode avoids these issues (see below). -

-

- The recordings will be saved in the "Output folder" named as "jack_capture_#.ext", where '#' is a number suffix and '.ext' the appropriate extension for the selected encoding format. -

-

- NOTE: We recommend the use of padding in your songs (ie, put some silence before the beginning and end of a song).
- This is because the very first sounds at the beginning of a song might not be timed properly (JACK apps need to catch up with the transport and start rolling). A padding of 8 beats is usually enough here.
- Also, when some applications reach their song end they might start-over transport at 0:00, which will cause the recording to never reach the "End Time" and thus never stop. -

- - -

Realtime vs. Freewheel

-

- In short, Realtime is the "live" version of audio you hear when making music. If you hear what you're doing, you're on realtime mode.
- Freewheel is the "offline" version, where audio (and midi) is processed as fast as possible. You won't hear anything when in this mode.
- During freewheel JACK will not allow new clients to be registered or connections to be made. It's literally meant to be used for recordings. -

-

- Rendering in freewheel is sometimes useful because both host and plugins can take as much time as they need to process, independently of the buffer size.
- This is also useful when your project gets too big and can no longer play in realtime without xruns. -

-

- Not all applications work in freewheel mode though, for example if it relies on any kind of event communication other than JACK-MIDI (like ALSA-MIDI or OSC).
- This is because JACK is running faster than realtime, so any external events can't catch up in time.
- We encourage you to use JACK-MIDI whenever possible. Not only does it allow freewheel rendering but also provides perfect timing between applications. -

- - -

Download

-

- Cadence-Render is available in the KXStudio repositories and ArchLinux AUR ('cadence-tools' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Cadence-XYController.php b/Applications:Cadence-XYController.php deleted file mode 100644 index 30cc3f9..0000000 --- a/Applications:Cadence-XYController.php +++ /dev/null @@ -1,93 +0,0 @@ - - - -

- Cadence-XY Controller is a simple XY widget that sends and receives data from Jack MIDI.
- It can send data through specific channels and has a MIDI Keyboard too. -

-

- This tool can be executed as 'cadence_xycontroller'. -

- - -

The Interface

-

- A screenshot follows showing the piano, running under
- cadence-xycontroller.png -

-

- Another screenshot, now running under Windows 8:
- cadence-xycontroller_win8.png -

-

- The XY widget is controlled by the mouse, and it syncs its values to the X and Y knobs. Moving the knobs will change the XY cursor accordingly.
- The "Smooth" checkbox will make XY cursor changes smoother (the cursor will follow the mouse with inertia), but it will not change the knobs' behaviour. -

-

- There's also a MIDI-keyboard that is usually hidden (use "Settings" menu, "Show MIDI Keyboard" to show or hide it).
- You can use the mouse or keyboard to trigger notes. The keyboard uses a 'qwerty' layout. -

- - -

Usage

-

- The first thing to do after starting this tool is to make the proper JACK connections so that it outputs the data somewhere (Catia does the job nicely).
-

-

- Cadence-XY Controller can both receive and send MIDI data. This data will not pass-through, which is intentional and not a design failure.
- MIDI channels used can be specified in the "Settings" menu. If data is received on a channel it's not set to listen to, such data will be ignored. -

-

- MIDI data will be sent whenever the keyboard or XY cursor changes. When everything is stationary, no data is sent.
- MIDI-Keyboard actions will send regular MIDI note-on/offs. XY cursor changes will send MIDI data that look like this:
- - Status:  0xB0 + channel - 1
- Control: 0x01 (Modulation, as defined in "X Controls")
- Value:   X value percentage * 127 / 100
-

-

- - -

Download

-

- Cadence-XYController is available in the KXStudio repositories and ArchLinux AUR ('cadence-tools' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux and Windows (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
- - - Windows 32bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Cadence.php b/Applications:Cadence.php deleted file mode 100644 index 0ce0bd4..0000000 --- a/Applications:Cadence.php +++ /dev/null @@ -1,85 +0,0 @@ - - - -

- Cadence is a set of tools useful for audio production.
- Cadence itself is also an application (the main one), which this page will document.
- There are other applications that are part of the Cadence suite, they are usually named as the "Cadence tools".
- They are: -

- -

- Some of these also have sub-tools, such as Cadence-JackMeter and Claudia-Launcher.
- Each of these sub-tools is properly documented in its respective page. -

-

- Cadence can be executed as 'cadence'.
- Running it with '--minimized' makes it start minimized in the systray. -

- - -

The Interface

-

- A screenshot of the first, "System" tab:
- (The panels on the left display system information and checks, and on the right you have the current status of the JACK server and bridges)
- cadence1.png -

-

- A screenshot of the second, "Tools" tab:
- (The screenshots are clickable, which will start their respective tools)
- cadence2.png -

-

- A screenshot of the third, "Tweaks" tab:
- (This tab allows you to carry out some audio and system related tasks. Some options are not available on certain systems)
- cadence3.png -

- - -

Download

-

- Cadence is available in the KXStudio repositories and ArchLinux AUR (both with 'cadence' package name).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux and Windows.
- - - Linux 32bit
- - - Linux 64bit
- - - Windows 32bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Carla-Control.php b/Applications:Carla-Control.php deleted file mode 100644 index 3332b63..0000000 --- a/Applications:Carla-Control.php +++ /dev/null @@ -1,75 +0,0 @@ - - - -

- This is a dummy page, a placeholder for when the real page is written. -

- - -

The Interface

-

- TODO -

- - -

Usage

-

- TODO -

- - -

Download

-

- Carla is available in the KXStudio repositories and ArchLinux AUR (both with 'carla' package name).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux (part of the Carla bundle).
- - - Linux 32bit
- - - Linux 64bit
- - - MacOS 64bit
- - - Windows 32bit (No SSE, for old PCs)
- - - Windows 32bit
- - - Windows 64bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Project page
- - - Source code (zip)
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Carla.php b/Applications:Carla.php deleted file mode 100644 index 3c37ad6..0000000 --- a/Applications:Carla.php +++ /dev/null @@ -1,119 +0,0 @@ - - - -

- Carla is an audio plugin host, with support for many audio drivers and plugin formats.
- It has some nice features like automation of parameters via MIDI CC (and send output back as MIDI too) and full OSC control.
-

-

- Carla currently supports LADSPA (including LRDF), DSSI, LV2, VST2/3 and AU plugin formats, plus GIG, SF2 and SFZ file support.
- It uses JACK as the default and preferred audio driver but also supports native drivers like ALSA, DirectSound or CoreAudio.
-

-

- There are 4 types of engine processing: -

- - - -

The Interface

-

- By default Carla uses its own internal theme, a screenshot of it follows along with some plugins:
- carla.png
- The user can keep the custom theme but use system colors, or simply disable the custom theme altogether.
- The result may not be as nice though.
-

-

- The 'Patchbay' uses the same canvas engine that Catarina, Catia and Claudia do:
- carla-patchbay.png -

-

- The last tab "Log" simply prints debug info from time to time when an internal error occurs, in a way that doesn't disturb the user.
- This tab is not available in the Windows version.
-

- - -

Usage

-

- The first time you run Carla you'll most likely want to scan for plugins.
- You can configure your plugin folders in the settings if needed. When done, use "Add New Plugin" in the toolbar, then press the "Refresh" button.
-

-

- Because Carla is a somewhat complex application, a single page is not enough to cover it entirely.
- (We're currently writing the rest of the pages so be back soon!) -

- - - - - -

Download

-

- Carla is available in the KXStudio repositories and ArchLinux AUR (both with 'carla' or 'carla-git' package names).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux, Mac and Windows (version 2.0-RC4).
- - - Linux 32bit
- - - Linux 64bit
- - - MacOS 64bit
- - - Windows 32bit (No SSE, for old PCs)
- - - Windows 32bit
- - - Windows 64bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Project page
- - - Source code (zip)
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Catarina.php b/Applications:Catarina.php deleted file mode 100644 index 9118eea..0000000 --- a/Applications:Catarina.php +++ /dev/null @@ -1,95 +0,0 @@ - - - -

- Catarina is a Patchbay test app, created while the PatchCanvas module was being developed.
- It allows the user to experiment with the patchbay, without using ALSA, JACK or LADISH.
- You can save & load patchbay configurations too.
-

- - -

The Interface

-

- A screenshot follows:
- catarina.png -

-

- The 'File' menu and 'Project' toolbar provides actions related to projects: the common new, open and save.
- The 'Patchbay' menu and toolbar allows you to control what's inside the canvas. You can add/remove groups, add/remove ports and manage connections.
- The 'Canvas' menu and toolbar gives you control over the canvas zoom. The menu has actions for printing and saving an image of the current canvas.
-

-

- As with all the Cadence tools, you can hide the toolbar via 'Settings' menu, and also configure Catarina.
- The configure dialog looks like this:
- catarina-configure.png -

-

- You can change the theme used for the canvas (more on that below) and wherever or not to use bezier lines (will use straight lines if off).
- Fancy Eye-candy has 3 states: -

- -

- (Note: Full eye-candy currently is EXPERIMENTAL, and will make Catarina crash at random times. The cause of the crashes are under investigation).
-

-

- You can also enable OpenGL for the canvas (so the entire 2D space is rendered in the GPU, which makes big projects render much faster) and Anti-aliasing.
- OpenGL is experimental within Qt4 itself, and will not work properly on all systems.
- Anti-aliasing has 3 states: -

- -

- Settings will be applied as soon as you press 'OK', no need to restart Catarina.
-

- - -

Download

-

- Catarina is available in the KXStudio repositories and ArchLinux AUR ('catarina' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux and Windows (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
- - - Windows 32bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Catia.php b/Applications:Catia.php deleted file mode 100644 index a20193a..0000000 --- a/Applications:Catia.php +++ /dev/null @@ -1,59 +0,0 @@ - - - -

- Catia is a JACK Patchbay, with some neat features like A2J bridge support and JACK Transport.
- It's supposed to be as simple as possible so it can work nicely on non-Linux platforms. -

- - -

The Interface

-

- A screenshot follows:
- catia.png -

- - -

Download

-

- Catia is available in the KXStudio repositories and ArchLinux AUR ('catia' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux and Windows (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
- - - Windows 32bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Claudia-Launcher.php b/Applications:Claudia-Launcher.php deleted file mode 100644 index 4a80320..0000000 --- a/Applications:Claudia-Launcher.php +++ /dev/null @@ -1,48 +0,0 @@ - - - -

- Claudia-Launcher is a multimedia application launcher with LADISH support.
- It searches for installed packages (not binaries), and displays the respective content as a launcher.
- The content is got through an hardcoded database, created and/or modified to suit the target distribution. -

- - -

The Interface

-

- A screenshot follows:
- claudia-launcher.png -

- - -

Download

-

- Claudia-Launcher is available in the KXStudio repositories and ArchLinux AUR ('claudia' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Applications:Claudia.php b/Applications:Claudia.php deleted file mode 100644 index 24df420..0000000 --- a/Applications:Claudia.php +++ /dev/null @@ -1,57 +0,0 @@ - - - -

- Claudia is a LADISH frontend; it's just like Catia, but focused at session management through LADISH.
- It has a bit more features than the official LADISH GUI, with a nice preview of the main canvas in the bottom-left.
- It also implements the 'Claudia-Launcher' add-application style for LADISH. -

- - -

The Interface

-

- A screenshot follows:
- claudia.png -

- - -

Download

-

- Claudia is available in the KXStudio repositories and ArchLinux AUR ('claudia' package in the KXStudio repositories, 'cadence' in AUR).
- - - ArchLinux (AUR)
- - - Debian/Ubuntu (via KXStudio repositories)
-

-

- Pre-compiled binaries are available for Linux (part of the Cadence bundle).
- - - Linux 32bit
- - - Linux 64bit
-

-

- The latest source code is hosted on github, together with bug reports, feature requests, etc.
- - - Source code
- - - Bug reports / Feature requests
-

- -


- - diff --git a/Artwork.php b/Artwork.php deleted file mode 100644 index 7228e41..0000000 --- a/Artwork.php +++ /dev/null @@ -1,84 +0,0 @@ - - -

The KXStudio Desktop theme uses QtCurve as the rendering engine, making it available on Qt3, KDE3, Qt4, KDE4 and Gtk2 applications.
-There is a Metacity and XFWM theme as well.
-The icon theme used is Oxygen. -

Here's some screenshots showing off the theme on different Desktop Environments:
-

- - - - - - -
-

kxstudio-kde3.png
-KDE3 (Trinity) -

-
-

kxstudio-kde4.png
-KDE4 -

-
-

kxstudio-xfce.png
-XFCE -

-
-

You can get the entire artwork in the Downloads section, just like any other application from us. -


-To properly apply this theme, you can follow these steps: -

- -

A XFWM decoration theme is available for XFCE. You might want to use 'Oxygen Mono Light|Dark' to get monochrome panel applets.
-Please note that Gtk3 is not supported at the moment. -


-

-

The Desktop Session

-

Besides the theme, the "KXStudio Desktop" also consists of (resumed): -

- -


-JACK integration
-We're talking about making the whole system JACK dependant. JACK is started as soon as the user logs in, using the last session settings or a pre-setup LADISH Studio.
-For non-JACK aware apps, bridges are used.
PulseAudio works nicely with JACK, although it needs a bit medium/high buffer size in order to work properly.
ALSA has a plugin for JACK too, although it's not perfectly stable.
SDL-Audio applications will need either a SDL->OSS->JACK, SDL->ALSA->JACK or SDL->PulseAudio->JACK bridge, since there's no native JACK support in SDL. If you're able to get an OSS->JACK bridge working, use it as it is preferred. -


-Audio Session management through LADISH
-There needs to be a tool to manage audio projects (and non-audio as well), and LADISH already provides this functionality.
-By integrating with LADISH, we can set-up custom JACK settings, apps and connections, and load it at any time, even when login in. -


-One-app-to-rule them all (Cadence)
-Cadence is our own app that controls the whole audio system, using JACK and LADISH.
-This is pre-alpha software though, and it's not even released yet (although it's already present in the KXStudio repositories for testing).
-A full Cadence explanation/tutorial will be available once it reaches Alpha 1 (first public release) -


-

-

The Desktop Environment

-

There are plans to make our own Desktop Enviroment (including Window Manager), based on Twindy.
-A *Mock-up* can be seen here.
-There's nothing done for it yet, and it won't be so soon, as there is plenty of stuff to do first ;) -

-


- - diff --git a/Development.php b/Development.php deleted file mode 100644 index 569c777..0000000 --- a/Development.php +++ /dev/null @@ -1,43 +0,0 @@ - - -

- This page is meant for people that want to contribute to KXStudio. -

-

- Please note that KXStudio has project pages in both SourceForge and Launchpad (you can check the respective links on the left).
- SourceForge does the website, code and repository hosting, while Launchpad is used for managing bugs, questions/answers and the RSS news feed.
- The Cadence tools don't use SourceForge or Launchpad, but are hosted on github instead at https://github.com/falkTX/Cadence. -

-

- If you're looking to report a bug in the Cadence tools, use the github "Issues" interface available here.
- For KXStudio related bugs click here.
-
-

- -

- Regarding KXStudio development, we currently need: -

- - -

- In any case, you should always check the KXStudio TODO List to find out what you can do.
- (You don't need to know programming to help). -

-

- KXStudio future plans are discussed here. -

-
- - diff --git a/Development:TODO.php b/Development:TODO.php deleted file mode 100644 index c9308ed..0000000 --- a/Development:TODO.php +++ /dev/null @@ -1,36 +0,0 @@ - - -

- This page contains a list of things left to do for KXStudio.
-
-

- -

- Tasks for common people (not Team restricted): -

- -
- - diff --git a/Documentation.php b/Documentation.php deleted file mode 100644 index ac8a9be..0000000 --- a/Documentation.php +++ /dev/null @@ -1,80 +0,0 @@ - - -

- If you're looking for help regarding an Ubuntu feature, please search within the - Ubuntu Forums.
- For general Linux Audio help, use the - LinuxMusicians Forums or - LinuxAudio Mailing List.
- You can also use IRC on irc.freenode.net (or .com) server, channel #kxstudio or #opensourcemusicians.
- A discord server is also available - here, - in case you prefer that over IRC.
- (The discord server is going away quite soon though, as we do not want to encourage usage of proprietary systems) -

- -

Documentation

- -

- Please note that documentation for KXStudio is a work in progress, if you need some information not available here, you can try: -

- - - -

-
- Some useful topics: -

- - -

- KXStudio Repositories -

- - - -

-
- KXStudio Manual -

- -

- (The manual is being written by Dan MacDonald with the assistance of Aaron Wolf, falkTX and the LinuxMusicians community). -

- -


- - diff --git a/Documentation:KXStudio12041:NetBootInstall.php b/Documentation:KXStudio12041:NetBootInstall.php deleted file mode 100755 index 4fb77f5..0000000 --- a/Documentation:KXStudio12041:NetBootInstall.php +++ /dev/null @@ -1,84 +0,0 @@ - - -

- This section describes how to install a minimal Ubuntu system using a Net-Boot ISO.
- After the base install is done, we'll proceed to upgrade Ubuntu to KXStudio. -

-

- There are some requirements you need to check before trying this:
- 1 - Your system is connected to the internet via cable;
- 2 - You've downloaded and burned a KXStudio Net-Boot ISO into a CD;
-

- -


- -
Step 1 - Boot from the ISO
-

- Make sure your PC is booting from CD drives (the F8 or F9 key during bios splash usually can change the boot media).
- If you can't find the key for that, make sure the CD drive is 1st device the PC tries to boot from (there's an option for that in the BIOS). -

- -


- -
Step 2 - Install the base system
-

- When you boot from the ISO, the first thing you'll see is a list of languages - pick yours.
- Tip: Use the 'F3' key now to change the default keyboard language too. -

-

- Now just click 'Enter' to start the installation. -

-

- You'll notice this installation method looks rather old, but it's this way because we didn't load any drivers or special stuff yet.
- You can browse through the interface using the keyboard. The mouse does nothing at this point. -

-

- This installation method is exactly the same in an Ubuntu or Debian net-boot ISO, and it's very similar to the "alternate" method.
- Note that if you never used this kind of methods to install a Linux system before, you probably should not install KXStudio this way!
- Please go with UbuntuStudio 12.04 as a base install, and upgrade to KXStudio afterwards. -

-

- Once you've installed the base system, it will automatically reboot. - You can remove the CD now. -

- -


-
Step 3 - Enable the repositories
-

- Login in the terminal with the user credentials you entered during the installation.
- Note: You won't get any feedback while entering the password - this is normal (actually a security feature). -

-

- When logged in, run these commands to enable the KXStudio repositories:
- - sudo apt-get update
- sudo apt-get install python-software-properties wget
- sudo add-apt-repository ppa:kxstudio-team/kxstudio
- sudo apt-get update
- sudo apt-get install kxstudio-repos
- sudo apt-get update
-
-

- -


- -
Step 4 - Install the KXStudio Desktop
-

- For this "final" step, you can follow the Upgrade From Ubuntu tutorial, since the steps are the same.
- Just skip to the Step 2 - direct link -

-

- Of course, you won't have any GUI at this point, so you need to use the command-line methods. -

- -


- - diff --git a/Documentation:KXStudio12041:ReleaseNotes.php b/Documentation:KXStudio12041:ReleaseNotes.php deleted file mode 100755 index 5f4952f..0000000 --- a/Documentation:KXStudio12041:ReleaseNotes.php +++ /dev/null @@ -1,54 +0,0 @@ - - -

- These are the release notes related to the KXStudio 12.04.1 Release, based on Ubuntu 12.04.1 LTS.
- We recommend you to take a look at the Ubuntu's 12.04 release notes too, - here.
- (Read the 'Kubuntu' notes if you use KDE, 'Xubuntu' for XFCE and so on). -

- -


- -

KXStudio 12.04.1 Live-DVD Notes

- - -


- -

Current 12.04.1 Notes

- - -


- - diff --git a/Documentation:KXStudio12043:About.php b/Documentation:KXStudio12043:About.php deleted file mode 100755 index f1f514d..0000000 --- a/Documentation:KXStudio12043:About.php +++ /dev/null @@ -1,113 +0,0 @@ - - -

- KXStudio 12.04.3 is an ISO release based on Ubuntu 12.04.3 LTS, made on 17/10/2013.
- Check the Live-DVD section in the Downloads page to download it (or just click here). -

- -

- The Live-DVD contains a highly optimized KDE desktop (version 4.11.1), together with a low-latency kernel (version 3.8).
- There's a lot of audio-related applications inside, with even more available to install via the repositories. -

- -

- The live system is based upon Kubuntu code with only a few tweaks (like auto-adding the live user to audio and video groups).
- Due to a Kubuntu backports issue is not possible to use Ubuntu's "LTS Enablement Stack", so the regular Xorg version is used. -

- -

Pre-installed applications

- -

- The list of pre-installed applications in the ISO follows, not listing audio plugins. -

- - - - -
- Audio - -     -     - - Other -
-
    - -
  • Ardour3
  • -
  • Audacious
  • -
  • Audacity
  • -
  • Bristol
  • -
  • Cadence (and sub-tools)
  • - -
  • Carla
  • - - - -
  • Giada
  • -
  • Guitarix
  • -
  • Hydrogen
  • -
  • Jamin
  • -
  • Laborejo
  • -
  • LinuxSampler
  • -
  • LisaloQt
  • -
  • LMMS
  • -
  • Mixxx
  • -
  • MusE
  • -
  • Non-Mixer
  • -
  • Non-Sequencer
  • -
  • Non-Session-Manager
  • -
  • Non-Timeline
  • - -
  • Petri-Foo
  • -
  • Phasex
  • -
  • Qsampler
  • -
  • Qsynth
  • -
  • Qtractor
  • -
  • Rakarrack
  • -
  • Renoise
  • -
  • Rosegarden
  • - -
  • SEQ24
  • -
  • SooperLooper
  • - -
  • Sunvox
  • -
  • VMPK
  • -
  • xjadeo
  • -
  • ZynAddSubFX
  • -
-
-     -     - -
    -
  • Blender
  • -
  • Clementine
  • -
  • Digikam
  • -
  • Firefox
  • -
  • Gimp
  • -
  • gparted
  • -
  • Inkscape
  • -
  • KDE base (ark, dolphin, gwenview, k3b, etc)
  • -
  • Kdenlive
  • -
  • LibreOffice (Impress and Writer)
  • -
  • Muon
  • -
  • QdvdAuthor
  • -
  • SMPlayer
  • -
  • Synaptic
  • -
  • VLC
  • -
  • Wine
  • -
-
- -


- - diff --git a/Documentation:KXStudio12043:ReleaseNotes.php b/Documentation:KXStudio12043:ReleaseNotes.php deleted file mode 100755 index 1464433..0000000 --- a/Documentation:KXStudio12043:ReleaseNotes.php +++ /dev/null @@ -1,43 +0,0 @@ - - -

- These are the release notes related to the KXStudio 12.04.3 Release, based on Ubuntu 12.04.3 LTS.
-

- -


- -

KXStudio 12.04.3 Live-DVD Notes

- - -


- -

Current 12.04.3 Notes

- - -


- - diff --git a/Documentation:KXStudio14042:About.php b/Documentation:KXStudio14042:About.php deleted file mode 100755 index 8866a27..0000000 --- a/Documentation:KXStudio14042:About.php +++ /dev/null @@ -1,115 +0,0 @@ - - -

- The information on this page is incomplete or outdated. -

- -

- KXStudio 14.04.2 is an ISO release based on Ubuntu 14.04.2 LTS, made on 27/07/2015.
- Check the Live-DVD section in the Downloads page to download it (or just click here). -

- -

- The Live-DVD contains a highly optimized KDE4 desktop, together with a low-latency kernel (version 3.8).
- There's a lot of audio-related applications inside, with even more available to install via the repositories. -

- -

- The live system is based upon Kubuntu code with only a few tweaks (like auto-adding the live user to audio and video groups). -

- -

Pre-installed applications

- -

- The list of pre-installed applications in the ISO follows, not listing audio plugins. -

- - - - -
- Audio - -     -     - - Other -
-
    - -
  • Ardour
  • -
  • Audacious
  • -
  • Audacity
  • -
  • Bristol
  • -
  • Cadence (and sub-tools)
  • - -
  • Carla
  • - - - -
  • Giada
  • -
  • Guitarix
  • -
  • Hydrogen
  • -
  • Jamin
  • -
  • Laborejo
  • -
  • LinuxSampler
  • -
  • LisaloQt
  • -
  • LMMS
  • -
  • Mixxx
  • -
  • MusE
  • -
  • Non-Mixer
  • -
  • Non-Sequencer
  • -
  • Non-Session-Manager
  • -
  • Non-Timeline
  • - -
  • Petri-Foo
  • -
  • Phasex
  • -
  • Qsampler
  • -
  • Qsynth
  • -
  • Qtractor
  • -
  • Rakarrack
  • -
  • Renoise
  • -
  • Rosegarden
  • - -
  • SEQ24
  • -
  • SooperLooper
  • - -
  • Sunvox
  • -
  • VMPK
  • -
  • xjadeo
  • -
  • ZynAddSubFX
  • -
-
-     -     - -
    -
  • Blender
  • -
  • Clementine
  • -
  • Digikam
  • -
  • Firefox
  • -
  • Gimp
  • -
  • gparted
  • -
  • Inkscape
  • -
  • KDE base (ark, dolphin, gwenview, k3b, etc)
  • -
  • Kdenlive
  • -
  • LibreOffice (Impress and Writer)
  • -
  • Muon
  • -
  • QdvdAuthor
  • -
  • SMPlayer
  • -
  • Synaptic
  • -
  • VLC
  • -
-
- -


- - diff --git a/Documentation:KXStudio14042:ReleaseNotes.php b/Documentation:KXStudio14042:ReleaseNotes.php deleted file mode 100755 index 2015683..0000000 --- a/Documentation:KXStudio14042:ReleaseNotes.php +++ /dev/null @@ -1,47 +0,0 @@ - - -

- The information on this page is incomplete or outdated. -

- -

- These are the release notes related to the KXStudio 14.04.2 Release, based on Ubuntu 14.04.2 LTS.
-

- -


- -

KXStudio 12.04.3 Live-DVD Notes

- - -


- -

Current 12.04.3 Notes

- - -


- - diff --git a/Documentation:KXStudio14045:About.php b/Documentation:KXStudio14045:About.php deleted file mode 100755 index acc6fd5..0000000 --- a/Documentation:KXStudio14045:About.php +++ /dev/null @@ -1,117 +0,0 @@ - - -

- KXStudio 14.04.5 is an ISO release based on Ubuntu 14.04.5 LTS, made on 09/06/2017.
- Check the Live-DVD section in the Downloads page to download it (or just click here). -

- -

- The Live-DVD contains a highly optimized KDE4 desktop, together with a low-latency kernel (version 3.13).
- There's a lot of audio-related applications inside, with even more available to install via the repositories. -

- -

- The live system is based upon Kubuntu code with several tweaks - (like disable file indexer and everything else that can introduce random xruns). -

- -


- -

Current 14.04.5 Notes

- - -


- -

Pre-installed applications

- -

- The list of pre-installed applications in the ISO follows, not listing audio plugins. -

- - - - -
- Audio - -     -     - - Other -
-
    - -
  • Ardour
  • -
  • Audacious
  • -
  • Audacity
  • -
  • Bristol
  • -
  • Cadence (and sub-tools)
  • - -
  • Carla
  • - - - -
  • Giada
  • -
  • Guitarix
  • -
  • Hydrogen
  • -
  • Jamin
  • -
  • LinuxSampler
  • -
  • LMMS
  • -
  • Mixxx
  • -
  • MusE
  • -
  • Non-Mixer
  • -
  • Non-Sequencer
  • -
  • Non-Session-Manager
  • -
  • Non-Timeline
  • - -
  • Petri-Foo
  • -
  • Phasex
  • -
  • Qsampler
  • -
  • Qsynth
  • -
  • Qtractor
  • -
  • Rakarrack
  • -
  • Rosegarden
  • - -
  • SEQ24
  • -
  • SooperLooper
  • - -
  • xjadeo
  • - -
-
-     -     - -
    -
  • Blender
  • -
  • Clementine
  • -
  • Digikam
  • -
  • Firefox
  • -
  • Gimp
  • -
  • gparted
  • -
  • Inkscape
  • -
  • KDE base (ark, dolphin, gwenview, k3b, etc)
  • -
  • Kdenlive
  • -
  • LibreOffice (Impress and Writer)
  • -
  • SMPlayer
  • -
  • Synaptic
  • -
  • VLC
  • -
-
- -


- - diff --git a/Documentation:KXStudio14045:ReleaseNotes.php b/Documentation:KXStudio14045:ReleaseNotes.php deleted file mode 100755 index 1337dd1..0000000 --- a/Documentation:KXStudio14045:ReleaseNotes.php +++ /dev/null @@ -1,52 +0,0 @@ - - -

- These are the release notes related to the KXStudio 14.04.5 Release, based on Ubuntu 14.04.5 LTS.
-

- -


- -

KXStudio 12.04.5 Live-DVD Notes

- - -


- -

Current 14.04.5 Notes

- - -


- - diff --git a/Documentation:KXStudio1804:About.php b/Documentation:KXStudio1804:About.php deleted file mode 100755 index 496a64f..0000000 --- a/Documentation:KXStudio1804:About.php +++ /dev/null @@ -1,115 +0,0 @@ - - -

- KXStudio 14.04.5 is an ISO release based on Ubuntu 18.04 LTS, made on 19/05/2018.
- Check the Live-DVD section in the Downloads page to download it (or just click here). -

- -

- The Live-DVD contains a highly optimized KDE5 Plasma desktop, together with a low-latency kernel (version x.xx).
- There's a lot of audio-related applications inside, with even more available to install via the repositories. -

- -

- The live system is based upon the Neon distribution with several tweaks - (like disable file indexer and everything else that can introduce random xruns). -

- -


- -

Current 18.04 Notes

- - -


- -

Pre-installed applications

- -

- The list of pre-installed applications in the ISO follows, not listing audio plugins.
- NOTE: This list is outdated! (was made for 14.04.5 and needs to be updated) -

- - - - -
- Audio - -     -     - - Other -
-
    - -
  • Ardour
  • -
  • Audacious
  • -
  • Audacity
  • -
  • Bristol
  • -
  • Cadence (and sub-tools)
  • - -
  • Carla
  • - - - -
  • Giada
  • -
  • Guitarix
  • -
  • Hydrogen
  • -
  • Jamin
  • -
  • LinuxSampler
  • -
  • LMMS
  • -
  • Mixxx
  • -
  • MusE
  • -
  • Non-Mixer
  • -
  • Non-Sequencer
  • -
  • Non-Session-Manager
  • -
  • Non-Timeline
  • - -
  • Petri-Foo
  • -
  • Phasex
  • -
  • Qsampler
  • -
  • Qsynth
  • -
  • Qtractor
  • -
  • Rakarrack
  • -
  • Rosegarden
  • - -
  • SEQ24
  • -
  • SooperLooper
  • - -
  • xjadeo
  • - -
-
-     -     - -
    -
  • Blender
  • -
  • Clementine
  • -
  • Digikam
  • -
  • Firefox
  • -
  • Gimp
  • -
  • gparted
  • -
  • Inkscape
  • -
  • KDE base (ark, dolphin, gwenview, k3b, etc)
  • -
  • Kdenlive
  • -
  • LibreOffice (Impress and Writer)
  • -
  • SMPlayer
  • -
  • Synaptic
  • -
  • VLC
  • -
-
- -


- - diff --git a/Documentation:KXStudio1804:ReleaseNotes.php b/Documentation:KXStudio1804:ReleaseNotes.php deleted file mode 100755 index dae885b..0000000 --- a/Documentation:KXStudio1804:ReleaseNotes.php +++ /dev/null @@ -1,44 +0,0 @@ - - -

- These are the release notes related to the KXStudio 18.04 Release, based on Neon 18.04 LTS. (which in turn is based on Ubuntu)
-

- -


- -

KXStudio 18.04 Live-DVD Notes

- - -


- -

Current 14.04.5 Notes

- - -


- - diff --git a/Documentation:Manual:alsa_and_kxstudio.php b/Documentation:Manual:alsa_and_kxstudio.php deleted file mode 100644 index 75c88b5..0000000 --- a/Documentation:Manual:alsa_and_kxstudio.php +++ /dev/null @@ -1,137 +0,0 @@ - - -
- -

-The Advanced Linux Sound Architecture is the primary sound system used by Linux. Even those who only plan to use JACK with the FFADO (FireWire) drivers should still have familiarity with ALSA. -

- -
- -

kmix

-
- -

-The main ALSA mixer included with KXStudio is called kmix. You can use kmix to adjust audio input and output levels, mute and unmute channels and change other non-FireWire audio device settings such as selecting between SPDIF and analog inputs if your device has such features. The kmix system tray icon looks like this: -

- -

-The kmix icon -

- -

-If you have a scrollwheel function on a mouse or trackpad, you can hover over the kmix tray icon and adjust the Master volume by moving the scrollwheel up and down. If you left-click on the kmix tray icon it will display a mini mixer. To see a full mixer with more controls, click the 'Mixer' button within the mini mixer menu. -

- -

-kmix mixer -

- -

-Here we see the main kmix mixer window. kmix displays the controls for each ALSA device on its own separate tab. In this screenshot the 'HDA Intel' onboard audio device is selected. -

- -

-You will notice that each fader has a small speaker icon just below it. When these speaker icons display a small red cross on them, as 'Beep' does in the screenshot, that indicates the channel is currently muted. You can toggle muting simply by left-clicking on the speaker icons. -

- -

-In the bottom right corner of the mixer window there is a tool icon. This icon allows you to configure which channels are available to control for the currently selected kmix device tab. You may find that some controls you need are missing at first, so you may add them via this Configure Channels window. A common example of when you might need to use the kmix Configure Channels window is if you are using any SPDIF (optical) ports, which are referred to as IEC958 devices under GNU/Linux, as such controls are often not displayed by default. -

- -

-Whilst there is a standard defined for USB audio devices, relatively few devices fully comply with it. What this means for ALSA and USB devices is that sometimes you will see no controls under kmix for some USB devices or controls may not function as expected. Such issues may be worked around by inserting an app such as Non mixer or jack_mixer between an audio source and the problematic output device until the issue is fixed within ALSA. -

- -
- -

Cadence and ALSA

-
- -

-Cadence is primarily used to control and monitor the various Linux sound systems, including ALSA, under KXStudio. The main Cadence window has a 'JACK bridges' section which contains two ALSA/JACK bridges - one for ALSA audio and one for MIDI. You will not hear audio produced by ALSA-only apps when JACK is running if the ALSA audio bridge is stopped. Likewise, you will be unable to access MIDI devices if the ALSA MIDI bridge isn't running when JACK is. -

- -
- -

non-JACK apps

-
- -

-As JACK increases in popularity, it is more widely supported. However, several apps are still ALSA-only. Such apps will have their audio channeled via the same ALSA to JACK bridge. These include: -

- -

-Adobe Flash Player (as used by Firefox and other browsers for sites such as YouTube) -

- -

-Skype If you don't require webcam or video support then it is recommended you use Mumble instead of Skype for VOIP. Although Mumble doesn't yet officially support JACK, there is a build of Mumble with JACK support available from the KXStudio repositories. However, if you need to use Skype it works fine provided the ALSA audio bridge is running. -

- -

-Many games and other various programs -

- -

-Some other apps have only partial JACK support. These work with JACK directly, have their own JACK connections, and function without the ALSA to JACK bridge, but their connections are not persistent. They will temporarily connect to JACK while playing but drop their connection as soon as playback is stopped. Examples of these apps are: -

- -

-Audacity -

- -

-SMPlayer -

- -

-VLC -

- -

-Hence, none of these offer the individual audio routing functionality or other features offered by fully JACK-native software. -

- -
- -

Useful ALSA commands

-
- -

-The following commands can be useful for troubleshooting ALSA issues in a terminal: -

-
alsamixer
- -

-The original ALSA mixer -

-
cat /proc/asound/cards
- -

-Displays attached ALSA devices -

-
cat ~/.asoundrc
- -

-Displays your ALSA configuration file -

-
sudo alsactl store 0
- -

-Saves the current settings for ALSA device 0 -

- -
- -


- - diff --git a/Documentation:Manual:cadence_introduction.php b/Documentation:Manual:cadence_introduction.php deleted file mode 100644 index e5772ca..0000000 --- a/Documentation:Manual:cadence_introduction.php +++ /dev/null @@ -1,144 +0,0 @@ - - -
- -

-Cadence controls and monitors various Linux sound systems as well as audio-related system settings. Below is a screenshot of its main window and following that is an explanation of what it all means and how you use it. -

- -

- -

- -
- -

System Information

-
- -

-This tells you the operating system, kernel version, and whether you are running a 32 or 64 bit OS. The kernel could be said to be the engine of Linux and KXStudio includes a low-latency kernel which has been optimized to get the best performance from JACK. -

- -
- -

System Status

-
- -

-This lets you select the CPU Scaling Governor, a property of the Linux kernel which controls the CPU speed. In 'performance' mode, your CPU will run at full speed all the time. This mode consumes the most power but ensures the best performance and minimum CPU-related sound issues. In many cases (especially on battery powered devices) using 'ondemand' makes more sense as this ups the CPU speed when its needed but clocks it back down when the computer is idle which helps save power. Note: to enable this option in KXStudio 12.04.1, you must first install “indicator-cpufreq” but this is included by default in 12.04.3. -

- -
- -

System Checks

-
- -

-Current kernel is a verification that you're running a realtime or lowlatency kernel. This check will be ticked already if you installed from the KXStudio ISO as it includes a low latency kernel. The other check verifies that your user is included in the audio group. Being a member of the audio group is required for your user to run JACK in realtime mode for optimal performance and is also required to access FireWire devices. -

- -

-The user created during installation of KXStudio 12.04.3 is automatically added into the audio and video groups but newly created users will not be part of these groups. You can add a user to the audio group by running: -

-
sudo adduser <username> audio
- -

-Replace <username> with a KXStudio user name when you run that command in a terminal. You will then need to log out and back in or reboot before the user will be recognised as being in the audio group. Alternately, you can manage users and groups using the graphical kuser tool which is included with 12.04.3. -

- -
- -

JACK Status

-
- -

-Server Status tells you if the JACK server is running or not. You cannot run any JACK-dependant software unless the JACK server is started beforehand. -

- -

-Realtime tells you if JACK is running with realtime scheduling or not. Realtime scheduling allows JACK to take priority over other programs being run and hence improves performance of JACK applications. -

- -

-DSP Load is the current CPU load estimated by JACK. If it gets too high you may experience performance issues. -

- -

-Xruns For JACK to operate smoothly and without drop-outs it requires that its buffers (the memory used to transport audio) provide a continuous stream of data. Whenever this data fails to arrive in time to satisfy the requests of a JACK app it causes an xrun which is often accompanied by a disruption to the sound output. The key to success with JACK is to eliminate (or at least minimize) xruns. -

- -

-Buffer size is measured in frames per second. It determines the latency between the audio being received by JACK and being sent to the output device. The smaller the buffer the lower the latency and, as a result, the higher the accuracy when monitoring audio for multitrack recording. 1024 is the default and is usually a safe value but smaller buffer sizes have less latency, i.e. less delay between the input and output. Try different settings to see how low you can go when recording without getting xruns. The functioning of lower size buffers depends on the power of your CPU and the specifics of your audio device. The lowest buffer size most decent quality audio devices can handle well is 64. -

- -

-Sample rate is the frequency JACK will run and record audio at. 44.1kHz is the CD audio standard, but 48kHz is more common to go with video or for other typical audio. Higher sample rates allow for higher quality but require more disk space. Even for professional purposes, 48kHz is usually fine as the default. Additionally, 48 and 96Khz allow for lower latency than using 44.1 or 88.2 due to the way it is calculated. -

- -

-Latency is the JACK capture latency which measures the time taken to fill the audio capture buffer. This value is determined by the buffer, period size and samplerate settings used to start JACK. -

- -
- -

JACK Controls

-
- -

-Start Starts the JACK server, if its not running. This is the recommended way to start JACK. -

- -

-Stop stops the JACK server. It is wise to save your work in any open JACK apps before stopping JACK, just to be safe. -

- -

-Force restart should 'Start' fail to start JACK, it is worth trying 'Force restart' but you may lose the last changes made to the JACK settings. -

- -

-Configure opens the JACK settings window, which is covered in the next chapter. -

- -

-Switch Master tells JACK to apply any changes made in the JACK settings window. -

- -

-Auto-start JACK or LADISH at login lets you pick if you'd like to start JACK or a LADISH studio at boot. KXStudio includes an app called Claudia which lets you create virtual 'LADISH' studios of interlinked audio applications. After creating such a studio within Claudia, you can use Cadence to configure your machine boot into a saved LADISH studio configuration. Starting a LADISH studio at boot also starts JACK using the settings defined within the studio. -

- -
- -

JACK Bridges

-
- -

-Cadence's main window integrates the control of a few 'JACK bridges' -services which enable alternate Linux sound systems to run seemlessly atop JACK. -

- -

-The ALSA audio bridge enables one or more ALSA audio applications to access your JACK device when it is started. Most everybody will want to ensure this is kept running alongside JACK as it enables audio for non-JACK apps such as Firefox. If you have chosen for JACK to start at boot then the ALSA audio bridge also gets started automatically. -

- -

-The ALSA MIDI bridge needs to be running if you want to use any MIDI hardware. -

- -

-PulseAudio is not included by default with KXStudio and the PulseAudio bridge will not function until it has been installed. Most applications which use PA can use ALSA or JACK instead so there is often no need for PA and its bridge. -

- -
- -


- - diff --git a/Documentation:Manual:downloading_and_booting_kxstudio.php b/Documentation:Manual:downloading_and_booting_kxstudio.php deleted file mode 100644 index 7beca3a..0000000 --- a/Documentation:Manual:downloading_and_booting_kxstudio.php +++ /dev/null @@ -1,80 +0,0 @@ - - -
- -

-The easiest way to try KXStudio and discover if it supports your hardware is to boot it directly off a DVD or a USB drive. You can easily do this on any computer without any effect on the currently installed system. Doing this is referred to as running a 'live' system. -

- -
- -

32 or 64 bit?

-
- -

-Download the KXStudio Live-DVD images from: -

- -

-http://kxstudio.linuxaudio.org/Downloads#LiveDVD -

- -

-Note: the image files are .iso format (which is just the initials of the International Standards Organization which defined the format). These contain the complete KXStudio operating system as well as many applications. -

- -

-You'll notice there are both 32 and 64-bit versions. Unless you are installing KXStudio to multiple, different machines you will only need one image file. If your machine allows for it, the 64-bit version is recommended as it usually works faster. Note that you can still run 32-bit software under a 64-bit installation but not the other way around. -

- -

-With the exception of maybe a few (mainly Atom CPU-based) netbooks and tablets; most laptops, notebooks and desktops since the middle of the last decade will have a 64-bit capable CPU. One sure sign is if your machine is running a 64-bit version of Windows then you know you can run 64-bit KXStudio. If you're unsure, the easiest way to find out is just to try booting the 64-bit version. However, 64-bit machines can still use the 32-bit installation, so the 32-bit option is functional for all systems. -

- -
- -

DVD or USB boot?

-
- -

-If your machine has a DVD drive and you have a blank DVD to spare then the easiest way to boot KXStudio is to burn the .iso to a DVD. Full instructions are available for burning an iso file to a DVD under Windows, Mac, and GNU/Linux. -

- -

-The other option is to boot from a USB drive. USB drives are faster than DVDs and can be set to save updates and work and function as a working system; but you won't experience the full speed and capacity of KXStudio until you install it to a hard drive. -

- -

-If using USB, you will need a FAT32 formatted USB drive with at least 2 GB free space. You can then use the freely available Easy2Boot,unetbootin or the Ubuntu Startup Disk Creator to transfer the iso file and make it boot from your USB drive. Easy2Boot requires a little more effort to set up than unetbootin or USDC but it allows you to boot multiple ISOs from a single USB drive, which is immensely useful. -

- -

-Using Unetbootin is as simple as selecting the 'Diskimage' option, browsing to and selecting your downloaded KXStudio iso file, selecting the correct USB drive from the 'Drive' drop-down menu and then clicking OK. After a few minutes wait you will be told when your USB drive is safe to be removed and ready to be booted. -

- -
- -

Booting KXStudio

-
- -

-Reboot your machine with the KXStudio DVD in the drive or with the Easy2Boot/unetbootin/USDC-modified USB drive attached. In rare cases, your computer will automatically boot KXStudio. Typically, however, you will need to find out how to enter the boot menu on your machine or enter the BIOS or UEFI menu to change the boot order so that the DVD and/or USB drive takes higher boot priority than the hard drive. Commonly, pressing F11 or F12 right at start up will bring up the boot options; pressing F2 will bring up the full BIOS menu. In other cases, DELETE or ESCAPE are used. If none of these work, refer to the manual for your computer or search online for machine-specific instructions. -

- -

-If you boot the DVD, you will first be prompted to choose the language to use. When this occurs, you can either do nothing and wait 30 seconds before the default of English is chosen and booting continues or you can use the arrow keys and ENTER to choose an alternate language. Booting off USB does not bring up the language selection menu directly; instead you may change language settings under 'System Settings'. -

- -
- -


- - diff --git a/Documentation:Manual:included_and_recommended_apps.php b/Documentation:Manual:included_and_recommended_apps.php deleted file mode 100644 index e8c7d1e..0000000 --- a/Documentation:Manual:included_and_recommended_apps.php +++ /dev/null @@ -1,169 +0,0 @@ - - -
- -

-Listed below are recommended audio, video and productivity apps for GNU/Linux complete with a short description. -

- -

-Many of these apps are, or will be, included on the KXStudio DVD. Those not included are easily installed from the repositories in most cases. -
- -

- - -
- -


- - diff --git a/Documentation:Manual:installing_kxstudio.php b/Documentation:Manual:installing_kxstudio.php deleted file mode 100644 index 9979d91..0000000 --- a/Documentation:Manual:installing_kxstudio.php +++ /dev/null @@ -1,162 +0,0 @@ - - -
- -

-There are a few important considerations you must be aware of before installing KXStudio. These include knowing what type of machine you are installing on, how its disks are to be arranged and whether or not you plan to boot any additional operating systems alongside KXStudio. -

- -

-REMEMBER TO ALWAYS BACK UP all important files before you start modifying partitions or trying to install new operating systems! -

- -
- -

Partitioning options

-
- -

-Whether you are installing onto a UEFI or BIOS-based machine you will have the least trouble getting KXStudio to boot if you are able to let the KXstudio installer use your entire hard drive and automatically create the partitions for you. In any case, make sure that important files on the machine are backed up before installation in case you make a mistake during partitioning! It will also help to know if your machine is UEFI or not before you start installing. -

- -

-If you want to install KXStudio onto the same drive as an existing installation of Windows read this guide on how to resize your Windows drive. -

- -
- -

UEFI, Windows 8 and SecureBoot

-
- -

-Many computers purchased since late 2011 use a technology called UEFI in place of the traditional BIOS to control and configure booting of operating systems. Due to UEFI being a new technology, GNU/Linux support is not yet as reliable as it is for older BIOS-based machines. In particular, Ubuntu and KXStudio cannot currently be dual-booted with Windows 8 with SecureBoot enabled without in-depth knowledge far beyond the scope of this guide. If you are hoping to dual boot Windows 8 with GNU/Linux you should look into disabling SecureBoot mode in your UEFI configuration. -

- -
- -

Multi-booting with UEFI

-
- -

-Those wishing to multi-boot Windows, OSX or other operating systems with KXStudio on a UEFI machine are recommended to obtain a copy of Linux Secure Remix before you attempt installing KXStudio. If, after installing KXStudio on the same UEFI machine as Windows or OSX and rebooting, you don't see a boot menu offering a choice of operating systems you should boot Linux Secure Remix and run the Boot-Repair tool which fixes most GRUB/UEFI boot configuration issues and should get your machine multi-booting properly. -

- -

-The Boot-Repair process is documented here. If Boot-Repair doesn't cure your UEFI booting woes it would be worth trying rEFIt or gummiboot./ -

- -
- -

Advanced partitioning options

-
- -

-By default, the main GNU/Linux system (root) uses the same partition as your user files (home). For various reasons, such as for ease of later system updates, you may want separate partitions. While ideal, this step is optional and can be skipped if you are uncomfortable with the details or want to save time. -

- -

-To customize your partitions, run “GParted” from the KXStudio live session before running the KXStudio installer. -

-
    -
  1. First, resize existing systems that you want to keep, if you have any
    -
  2. -
  3. Create a new “extended” partition in the empty space
    -
  4. -
  5. Within the extended partition, make a logical partition for your root (/) of at least 15GB and formatted as ext4. This will contain the OS and apps.
    -
  6. -
  7. Also within the extended partition, make a small partition for swap (virtual RAM) that is at least as large as your physical RAM size and put it at the end of the drive
    -
  8. -
  9. Again within the extended partition, create a logical ext4 partition for home (/home) for all your user files and preferences. Use all the remaining space or consider making a separate partition for media files
    -
  10. -
- - -
- -

Running the installer

-
- -

-The KXStudio Live DVD is based upon Kubuntu 12.04.3 and uses the same installation tool so you can reference the official Ubuntu Install guide. The only real difference is in step 7 as you will need to click the 'Install KXStudio' icon on the desktop instead of clicking 'Install Ubuntu' when you are ready to run the installer, that is if you chose to 'Try KXStudio before installing' instead of choosing to run the installer directly at boot. -

- -

-Contrary to what the Ubuntu installer seems to recommend with its network check, it is recommended that you disconnect from the internet before and whilst you install KXStudio so that updates are not fetched and the process is completed as quickly as possible. After a successful install and reboot you will be prompted to install any available updates. -

- -

-If you did the advanced partitioning to separate your root and home, choose “manual” for partitioning in the installer. Mark to use your intended root partition as / and your intended home partition as /home, keeping the ext4 format for both. -

- -
- -

KXStudio Welcome Setup

-
- -

-After installing and booting KXStudio for the first time, you will see the KXStudio Welcome screen. It is recommended you choose 'Force reset of all settings' if you have just completed a fresh install. 'Update basic settings' may be useful to people running KXStudio Welcome on an existing installation or /home partition who don't want to replace all of their settings. -

- -

-Using the KX Welcome 'Update Theme' is known to cause text visibility issues for certain web sites and apps such a qtractor so use this option with caution. Update theme has a screenshot option that gives you a preview of what the desktop looks like with its modifications applied. -

- -
- -

Multi-boot issues on BIOS-based machines

-
- -

-Sometimes the installer fails to detect the operating systems and/or add the correct options to the GRUB boot menu ie no option to boot into Windows. To fix a boot menu on BIOS-based machines, it is usually sufficient to run: -

-
sudo update-grub
-sudo grub-install /dev/sda
- -

-Type those commands into a terminal after booting into KXStudio and then reboot to check the new updated GRUB config. These commands make GRUB scan for other installed OSes, update its configuration and then write its updated configuration to the first HD which is /dev/sda. -

- -

-Super Grub2 Disk is very useful for fixing GRUB boot issues as it allows for booting Linux partitions on UEFI machines as well as legacy BIOS machines even when GRUB is missing or incorrectly configured. -

- -

-Another useful tool to ease GRUB2 configuration is GRUB Customizer. -

- -
- -

Important notes for SSD users

-
- -

-If you have installed KXStudio onto an SSD, you may experience frequent stalls early in the boot process at the KXStudio boot splash screen. You can fix this by running: -

-
kdesudo kate /etc/default/grub
- -

-Remove the word 'splash' from the GRUB_CMDLINE_LINUX_DEFAULT options, save the file then update and re-install GRUB using the two commands from the previous multi-boot section. -

- -

-The KXStudio installer does not tweak the configuration of Solid State Drives for optimal performance. Follow this guide to optimize the performance of your SSD drives. -

- -
- -


- - diff --git a/Documentation:Manual:jack_configuration.php b/Documentation:Manual:jack_configuration.php deleted file mode 100644 index 4e9dff8..0000000 --- a/Documentation:Manual:jack_configuration.php +++ /dev/null @@ -1,99 +0,0 @@ - - -
- -

-Most of JACK's important configuration options are set within the Driver tab of Cadence's JACK Settings window which you can access via Configure under Cadence's main window, as shown below: -

- -

-JACK Settings -

- -
- -

JACK Driver

-
- -

-The driver column to the left selects which JACK driver you wish to configure and use next time you start JACK with Cadence. Those using FireWire devices should use the FireWire driver but otherwise you should select ALSA for your JACK driver. -

- -

-The top 3 drop-down options within Cadence's ALSA driver configuration are the most important as these let you select which device(s) to use for physical audio IO. If 'Duplex Mode' is enabled then you can assign different ALSA devices to handle Input and Output individually. This could be useful, for example, if you need a mic input but wanted to have your sound output via a USB audio device that doesn't have a mic input. In this case you could use your computers onboard ALSA device, which likely does have a mic input, as a separate input device. If Duplex Mode is not selected then the top drop-down is used to select the ALSA device to use for both audio input and output. -

- -
- -

JACK Properties

-
- -

-Sample Rate, Buffer Size and Periods/Buffer determine the base JACK latency. Their default values of 48000, 1024 and 2 respectively should work with most devices but a latency over 10ms is not usually considered good enough to be called realtime. Anyone interested in multitrack recording may wish to experiment with these settings to achieve the lowest, xrun-free latency their hardware will allow. It is possible to achieve 1ms latency with good hardware and the correct configuration. -

- -

-Sample Rate Due to the way latency is calculated, it is recommended you use 48000 or 96000Hz for the lowest latency. -

- -

-Buffer A smaller buffer gives lower latency. The lowest size most devices can handle is 64. Lower quality hardware may not handle any lower than 512. -

- -

-Periods/Buffer The larger the period size, the higher the latency but the less chance of xruns. Experiment with using 2 or 3 periods/buffer. -

- -

-Extra Latency To achieve the highest level of precision in overdubbing you should provide the extra latency values (in frames) which can be obtained with jack_iodelay. This process is covered in the Latency chapter. -

- -
- -

Checking for errors with cadence-logs

-
- -

-If JACK fails to start you can find out whats causing the problem by checking the Cadence logs. You can access the Cadence logs by launching it from under the 'Tools' tab of the main Cadence window or you can run cadence-logs from a terminal. -

- -
- -

JACK and FireWire

-
- -

-kmix and alsamixer do not support FFADO. To adjust levels, enable phantom power and change other options for FireWire devices use ffado-mixer after you have started JACK with the FireWire driver. If you have trouble, running ffado-diag in a terminal may tell you more than Cadence's JACK error logs. -

- -
- -

rtirq configuration

-
- -

-This is an optional step that can help reduce latency. rtirq is a script that detects audio devices and prioritises them with the kernel according to a list specified in its configuration file. KXStudio's default rtirq configuration looks like: -

- -

-RTIRQ_NAME_LIST=“firewire snd usb i8042” -

- -

-Here we see FireWire devices have priority over ALSA and USB devices because its mentioned first. If you are mainly running JACK on a USB device you may wish to make usb the first item in the list by editing that line in the rtirq config file with a command such as: -

-
kdesudo kate /etc/default/rtirq
- -
- -


- - diff --git a/Documentation:Manual:kxstudio_and_free_software.php b/Documentation:Manual:kxstudio_and_free_software.php deleted file mode 100644 index b195f39..0000000 --- a/Documentation:Manual:kxstudio_and_free_software.php +++ /dev/null @@ -1,108 +0,0 @@ - - -
- -

-Along with the Debian and Ubuntu base systems and the whole GNU/Linux world, KXStudio has its roots in the Free Software movement led by Richard Stallman and the GNU project. All of the custom KXStudio tools are FLOSS, as is the vast majority of other included software. -

- -

-As KXStudio's primary purpose is to make the installation of a GNU/Linux-based audio/visual workstation as easy as possible, a few non-free additions are included where they assist that goal. -

- -
- -

Non-free software from Ubuntu

-
- -

-The current KXStudio ISO is based upon Ubuntu which includes select non-free software. The Ubuntu non-free software is listed in separate repositories marked as either “non-free”, “restricted”, or “multiverse”. See help.ubuntu.com/community/Repositories for more information. Also, the standard Linux kernel includes some “binary blobs” — i.e. sections that have no source available (and so hamper the freedom to modify). -

- -

-The main non-free software that KXStudio includes from Ubuntu is Flash Player. Many websites still, unfortunately, depend upon Adobe Flash, so Flash Player provides the smoothest user experience. Thankfully, the FLOSS standards Webm and HTML5 are becoming increasingly popular, and there is a FLOSS Flash-replacement called GNASH. Hopefully there will be less need for the non-free Flash Player in the future. -

- -

-Ubuntu also includes some non-free codecs for accessing proprietary file formats. -

- -

-Some hardware manufacturers, particularly among wireless cards and graphics accelerators, do not make FLOSS drivers for Linux but create proprietary non-free drivers. FLOSS alternatives often function well enough, and KXStudio does not include proprietary drivers. However, because the proprietary drivers often provide superior performance, KXStudio includes a simple program to install them. See the separate page on installing non-free video drivers. -

- -
- -

Specific KXStudio non-free software

-
- -

-While all KXStudio PPA listings are otherwise strictly FLOSS, KXStudio includes non-free extras kept in a segregated repository. The packages are listed in Muon Package Manager By Origin under “KXStudio (Extra)”. In the software sources, the repository is “http://kxstudio.linuxaudio.org/repo/ precise free non-free”. -

- -

-The KXStudio non-free repository includes the following: -

- - - - - - - - - -
- -

What if I want to avoid non-free software?

-
- -

-Specific non-free software can be manually uninstalled, see the instructions for package management. Aside from the items listed above, another way to quickly identify a good portion of installed non-free software is to install the program vrms, the Virtual Richard M Stallman. Running vrms will bring up a list of non-free issues on your system, although it does not catch everything. -

- -

-To remove non-free software from the package listings, choose “Configure Software Sources” under “Settings” in Muon Package Manager. There, you can uncheck the Proprietary drivers and multiverse (copyright or legally problematic) listings. On the “Other Software” tab, you can remove the Medibuntu and kxstudio.linuxaudio.org repositories. -

- -

-If you want to use strictly 100% Free Software, there are several options. Instead of using the KXStudio ISO, KXStudio repositories can be added to any Debian-based system (which includes all Ubuntu-related systems) and you can leave out the separate non-free KXStudio repository. Debian itself is 100% Free (unless the user chooses to install extra non-free software). Additionally, FSF-endorsed distributions Trisquel (based on Ubuntu) and gNewSense (based on Debian) are also compatible with the KXStudioe repositories. Of these, only Debian is officially supported, but the others should work as well. -

- -
- -


- - diff --git a/Documentation:Manual:kxstudio_introduction.php b/Documentation:Manual:kxstudio_introduction.php deleted file mode 100644 index cf14ae4..0000000 --- a/Documentation:Manual:kxstudio_introduction.php +++ /dev/null @@ -1,61 +0,0 @@ - - -
- -
- -

What is KXStudio?

-
- -

-KXStudio is a large and frequently updated collection of audio/visual software for GNU/Linux. KXStudio is also the name given to a freely distributed GNU/Linux distribution, currently based on Ubuntu. The full KXStudio includes many system tweaks, applications, and tools not found within common GNU/Linux operating systems (distributions). KXStudio makes it easy to set up and use a free software-based digital audio/visual production environment. As well as this primary goal, KXStudio comes prepared to perform a wide variety of common computing tasks. -

- -
- -

What is this KXStudio manual for?

-
- -

-This short manual was created for the KXStudio DVD or USB install. KXStudio works with pretty much any PC, laptop, or netbook with a suggested (but not absolute) minimum of 1GB RAM and 8GB free hard drive space. These instructions are written for newcomers to GNU/Linux operating systems. The intent is to provide an overview of both the installation process and a brief introduction to GNU/Linux audio/visual production applications including understanding and using the most important aspects of KXStudio's custom audio tools. -

- -
- -

Who created KXStudio and for what purpose?

-
- -

-The KXStudio distribution is based upon Ubuntu, one of the most popular variants of the GNU/Linux operating systems. Ubuntu is itself developed by a company called Canonical along with an extended global community of users and developers. An increasing number of third party software companies also offer software and support. While this manual focuses on installing KXStudio as a complete system, the KXStudio software repositories can also be added as a supplement to any Ubuntu- or Debian-based system. -

- -

-KXStudio began when a talented young Portuguese developer known online as falkTX saw the need for Ubuntu to have better management tools and software compilation for audio-related work. Over the years, falkTX's work has expanded to cover the base KXStudio project, the related suite of audio tools known as Cadence, the Carla plugin host, and the DISTRHO audio plugins. falkTX puts an incredible amount of time and effort into creating and supporting these and has also assisted in improving numerous other FLOSS projects. If you appreciate his ongoing hard work he would be grateful for any contributions you can make via http://kxstudio.linuxaudio.org/Donations . Thank you! -

- -
- -

How does KXStudio differ from MS Windows or Mac OS X?

-
- -

-If you are familiar with MS Windows or OSX already, please be aware that although KXStudio can, in most cases, fully replace these commercial operating systems, it is not intended as a drop-in replacement for either. It is possible to run many MS Windows programs under GNU/Linux via a program called Wine, and both Mac OSX and Linux are variants of the UNIX family of operating systems, but the overall GNU/Linux experience is quite distinct. You will have to adjust to the GNU/Linux way of doing things if you want to run KXStudio. Don't worry about it though because both Windows and Mac users will discover many of their computer skills transfer easily over and getting help online is free and easy. The GNU/Linux community is very friendly and active, and you can directly converse with the makers of the software in a way that doesn't happen in the Windows and OSX world. -

- -

-It is also important to note that not all hardware manufacturers support Linux yet so if you are buying any hardware especially for use with KXStudio you should do your research first. Don't presume that just because something works or doesn't work under Windows that it will be so under KXStudio. Linux has a few sore spots for hardware support that are mostly the fault of secretive, non-co-operative manufacturers, but, conversely, Linux also supports lots of older hardware that may not work at all with modern versions of Windows. See the Useful Links section of this manual for various Linux hardware compatibility reference sites. -

- -
- -


- - diff --git a/Documentation:Manual:latency.php b/Documentation:Manual:latency.php deleted file mode 100644 index 6b49610..0000000 --- a/Documentation:Manual:latency.php +++ /dev/null @@ -1,124 +0,0 @@ - - -
- -
- -

Compensating for loopback latency

-
- -

-Although latency mostly refers to buffer size which delays immediate feedback of input, there is additional latency due to the basic processing of your audio interface. There is no way to reduce this “loopback” latency, but its existence will affect the timing of recorded overdubs. To address this, you can tell programs what the delay amount is so that compensation can be made, i.e. the recorded audio will be adjusted in time to account for this delay. Software alone cannot discover what the loopback latency is, so the following procedure is needed to determine the amount of compensation required: -

- -

-You will need a loopback cable capable of connecting your audio device's physical input to its physical output. -

- -

-1 - Connect your (mic) input to your (headphone) output with the loopback cable -

- -

-2 - Start JACK with known good settings -

- -

-3 - Open a terminal and run jack_iodelay. It will print 'Signal below threshold…' until we make the JACK connections -

- -

-4 - Use Catia or Claudia to connect the system capture_1 to 'jack_delay in' and connect 'jack_delay out' to the system playback_1 port -

- -

-5 - With both physical and JACK connections made, jack_iodelay should print output such as 'use X for the backend arguments -I and -O' -

- -

-6 - In the terminal, use ctrl-C to stop jack_iodelay -

- -

-7 - In Cadence or Claudia, open the JACK settings and enter the value X from jack_iodelay for both the the input and output extra latency values -

- -

-8 - Engage the new JACK settings with the “Switch Master” button. If you re-run the above test there should be no additional loopback latency. -

- -

-This information is used to tell programs how to adjust recordings so that the recorded result will line up precisely with how the original performance aligned with the previous tracks. -

- -

-Because these settings are not saved in the software to go with the interface choice, you'll need to change them every time you switch devices. The easiest way to do this is to have Claudia sessions for each device so all the settings are saved together. -

- -
- -

Minimizing xruns

-
- -
- -

Disable wireless internet

-
- -

-Wifi adapters have been known to cause random xruns. Some laptops have an external hardware switch to disable wifi. Otherwise, uncheck “enable wireless” in the KDE system tray's network control. If primarily using ethernet, consider disabling wifi (aka 802.11 a/b/g/n) in the BIOS or UEFI menu. -

- -
- -

Close unnecessary programs

-
- -

-In general, avoid running unnecessary, CPU-intensive programs when recording. -

- -

-Many pop-up ads and popular web sites make use of Adobe Flash. If you have any browser tabs open, it only takes one to be using a little bit of Flash to cause a big loss of CPU, lower latency and more xruns. The easiest way to avoid this is to close any web browsers. -

- -
- -

Avoid realtime resampling

-
- -

-When using Digital Audio Workstations and similar apps such as samplers etc, it is recommended you convert any sound files you wish to import to use the same sample rate as the one you are using for JACK. Many apps let you import and use sound files of different sample rates to the one you are running JACK with but then attempt to resample the audio 'on-the-fly' and this leads to xruns if your CPU cannot keep up. -

- -

-You can check the sample rate of audio files using your favourite media player such as smplayer (push CTRL+I when playing your file) or VLC (push CTRL+J) or you can find out from the terminal using mediainfo. soundkonverter and XCFA are good tools for batch conversion of audio files. -

- -
- -

Check for IRQ conflicts

-
- -

-Open a terminal and run: -

-
cat /proc/interrupts
- -

-Ensure that your audio driver is not sharing an IRQ with another device. Fixing this can be as simple as changing which port a USB audio device is using, but otherwise see this guide to fixing IRQ conflicts. -

- -
- -


- - diff --git a/Documentation:Manual:linux_audio_overview.php b/Documentation:Manual:linux_audio_overview.php deleted file mode 100644 index 2b1fcb6..0000000 --- a/Documentation:Manual:linux_audio_overview.php +++ /dev/null @@ -1,61 +0,0 @@ - - -
- -

-Anyone intending to use GNU/Linux as a platform for audio or video production will benefit from understanding the primary Linux sound sub-systems, their purposes and limitations. -

- -
- -

ALSA

-
- -

-ALSA, the Advanced Linux Sound Architecture, is a collection of drivers and libraries that provide Linux with audio and MIDI support for onboard, PCI, and USB audio hardware. ALSA doesn't support FireWire audio devices — that requires FFADO and JACK (see below). -

- -

-ALSA alone is insufficient for most AV production tasks because only one application can access an ALSA device at any one time. JACK and Pulseaudio were created mainly to overcome this restriction although they target different use cases. KXStudio includes an ALSA/JACK bridge program called “snd-aloop daemon” which enables the user to run ALSA-only apps alongside JACK and other JACK-native software. This bridge is turned on by default when JACK is started - see the Cadence instructions for more information. -

- -
- -

JACK

-
- -

-The JACK Audio Connection Kit is a program (jackd aka the JACK server) and a protocol/API that enables the connection of a number of different applications to an audio device as well as allowing them to share audio and/or MIDI data between themselves. JACK applications may be connected on the same machine or remotely over a network. Think of JACK as a virtual audio patch panel, like on a physical mixing desk. While making these connections is not always automatic, the JACK system provides unparalleled flexibility for combining different tools in whatever way you wish. JACK has become the pro-audio application interconnection standard under GNU/Linux and is becoming increasingly popular on other platforms. -

- -
- -

FFADO

-
- -

-FFADO provides Free FireWire Audio Drivers (the “O” is for .Org). Unlike ALSA, FFADO depends upon JACK and does not work independently. Hence, when you select a FireWire audio device for use by JACK under the Cadence driver configuration, you are using the FFADO drivers. -

- -
- -

PulseAudio

-
- -

-PulseAudio (PA) is a sound server which, like JACK, runs on top of ALSA to provide functions such as allowing more than one application to use an ALSA device simultaneously. Pulse is targetted at regular desktop and mobile users rather than low-latency audio production. Cadence includes a PulseAudio/JACK bridge enabling you to run PulseAudio apps under JACK, but there are very few apps which support PA without supporting JACK or ALSA. KXStudio does not include PulseAudio as part of the default installation, but it is easily installed with the package manager if required. -

- -
- -


- - diff --git a/Documentation:Manual:package_management.php b/Documentation:Manual:package_management.php deleted file mode 100644 index 5273cf0..0000000 --- a/Documentation:Manual:package_management.php +++ /dev/null @@ -1,151 +0,0 @@ - - -
- -

-In GNU/Linux, a “package” is a compressed file that usually contains a program or program data. The process of installing and removing software from packages is called package management. -

- -

-KXStudio is based upon Ubuntu which is itself based on Debian GNU/Linux, so as a result KXStudio uses .deb packages along with the Ubuntu software repositories (repos). The KXStudio part is the pre-configured PPA's (Personal Package Archives) which supplement the Ubuntu repositories. -

- -

-In KXStudio 12.04.3, the main package manager is called Muon. Muon is the easiest way to manage your software under KXStudio. KXStudio also includes the older Synaptic package manager and these instructions largely apply to that as well. -

- -
- -

System Upgrade

-
- -

-For increased system stability and security, it is recommended you keep all packages up-to-date. If your machine was not connected to the internet when you installed KXStudio, then the first thing you should do after installation is connect to the internet to perform a system upgrade. Note: you can always browse and remove packages from Muon but performing a system upgrade or installing new software from the repositories requires an internet connection. -

- -

-Muon Update Manager is a simple program which automatically checks for and alerts you about updates. There will be an icon in the system tray to show you when updates are available. -

- -

-If you want to manually check for updates, first open Muon Update Manager or instead the full Muon Package Manager, then click 'Check for updates'. After it has finished checking for updates, it will tell you in the status bar at the bottom of its window how many upgradeable packages are available. If there are any updates, click 'Full Upgrade' then 'Apply Changes'. It will then ask you for your password before upgrading the system to the latest package versions. -

- -

-Most programs will be ready as soon as updating has finished. In the case of some packages, such as the kernel, you will have to reboot before your updates can take effect. -

- -
- -

Installing packages

-
- -

-There are two main ways to install a package. If the program you want is available from the repositories it is recommended you install it from there. Not only is that easier than having to find a standalone package, you can trust it more and it will get automtically updated when you do a system update, after an update becomes available. -

- -
- -

Installing packages via Muon

-
- -

-Start Muon Package Manager, then type either the name of the program you want or search using a descriptive term. -

- -

-When you have found the package you want, select it by clicking and then press the 'Mark for Installation' button in the package details tab below or right-click the listing itself and choose 'Mark for installation'. -

- -

-If the chosen app requires additional packages be installed for it to function, then you will be asked to confirm the installation of the required additional packages. These extra packages are referred to as dependencies, and most reasonably complex programs have multiple dependencies. You can proceed to mark additional packages for installation and whenever you are ready install click 'Apply Changes' in the toolbar at the top. Muon will then ask you for your password before it downloads and installs the requested packages. -

- -

-If you install a graphical application you should be able to find and run it by typing the program name in the KDE menu search box. -

- -
- -

Installing from a .deb package file

-
- -

-There are many reasons why you should always try to install software from the repositories (or PPA's) rather than from .deb package files. Aside from saving time, using repositories ensures you are getting the correct packages for your distribution and then they will be automatically updated. In some cases, a .deb file will automatically install a repository to keep things updated, but not always. You will normally want to find repository versions or add PPA's to get software. -

- -

-Confusingly, there are multiple version of Ubuntu, many packages are available in 32- or 64-bit flavours. When installing software that is only available in .deb packages (named from Ubuntu's parent distro called Debian), look for the option that best matches your installed system. KXStudio is based upon kubuntu 12.04(.3) which is codenamed Precise so it is compatible with packages made for that distribution. Make sure you get the 32- or 64-bit package as appropriate. The main Cadence window tells you if you are running a 32 bit (aka i386 or i686) or 64 bit (amd64) system. -

- -

-Finding the correct package version is often the hardest part of installing from a .deb package. Installation is then straightforward enough. Firefox may be set to automatically open the installer when the file is downloaded or you can double-click the .deb package in the Firefox Downloads window to start installation. Otherwise, open Dolphin (the file manager), find the package you want to install and left click on it once. This opens the package with a program called gdebi-kde which will present you with an 'Install Package' icon you must click to install the package. What usually happens is you will be prompted for your password, and then you may find you will need to click 'Install Package' a second time before the package gets installed. -

- -
- -

Removing packages

-
- -

-In Muon, search for the package you wish to remove then select 'Removal' or 'Purge' from the “Mark for:” option within the package details tab or choose the corresponding option by right clicking on a package listing. If the program is already installed, the options will be either 'Mark for Removal' which simply removes the package or 'Mark for Purge' which also removes the programs settings. After having found and selected all the packages you wish to remove click 'Apply Changes'. You will then be prompted for your password. -

- -
- -

Removing unneeded dependencies

-
- -

-Removing a package will not remove the dependencies which may have been installed with it. To remove such extra packages if nothing else installed requires them, within Muon Package Manager, go to the Edit menu and choose “Remove unnecessary packages.” Then, as with all other procedures, you will have to click “Apply Changes” and enter your password. -

- -
- -

Adding further Personal Package Archives (PPA's)

-
- -

-The KXStudio repositories are themselves PPA's. In some cases, you may want to add new PPA's to your system. -

- -

-PPA's are especially useful if you want to help do beta testing or try pre-release versions of programs. In other cases, such as for KXStudio, PPA's supply stable releases that aren't maintained or up-to-date in the main system repositories. Installing from a PPA is easier and recommended in most cases over installing from .deb packages or compiling from source. -

- -

-If a PPA is available, it will usually be listed on the projects website. For example, the latest stable release of LibreOffice isn't in the main repositories because it hasn't had completely thorough testing under this version of Ubuntu. LibreOffice offers a PPA for the stable version and another for beta testing. The address for the stable PPA is: ppa:libreoffice/ppa -

- -

-To add the new PPA, open Muon and choose “Configure Software Sources” from the “Settings” menu then enter your password. In the window that appears, choose the tab “Other Software”. Click the “Add…” button and enter the PPA's address. -

- -

-The maintainers of each PPA will keep your software up-to-date, so you only need to install it once. Then, after an update check in Muon, the packages will be listed for update or available for installation if no previous version was installed. -

- -
- -

Repair broken packages

-
- -

-If a package installation fails or you have package management issues such as being unable to install additional packages due to unresolved dependencies then try running one (or both) of the following commands from a terminal, such as Konsole -

-
sudo apt-get install -f
-sudo dpkg --configure -a
- -
- -


- - diff --git a/Documentation:Manual:simple_claudia_studio.php b/Documentation:Manual:simple_claudia_studio.php deleted file mode 100644 index 214bd2d..0000000 --- a/Documentation:Manual:simple_claudia_studio.php +++ /dev/null @@ -1,86 +0,0 @@ - - -
- -

-JACK enables complex routing of audio and MIDI data between JACK-enabled apps. This enables the user to create their own custom instruments or virtual studios by combining several JACK apps. However, having such power would be of limited use if you had to manually patch programs together every time you wanted a specific configuration. This problem is addressed by JACK session managers such as LADISH. -

- -

-KXStudio includes an app called Claudia which uses the LADISH JACK session management protocol to save and restore JACK configurations or 'LADISH Studios'. Claudia is one of two JACK patchbay apps included in KXStudio for making and removing JACK connections. The other app is Catia, a simpler program with no canvas preview and no saved connections (and available for Windows and OSX, unlike Claudia). -

- -

-The use of Claudia and LADISH is best demonstrated with a simple example scenario. Let's say that you frequently find yourself wanting to record audio from a non-JACK app such as Firefox and you use qtractor to record the audio. To do this you must ensure JACK and Cadence's ALSA audio bridge are running and you must connect the alsa2jack capture ports to qtractor's JACK inputs. In this guide we will create a simple LADISH studio with Claudia that will start JACK and the ALSA bridges, load qtractor and connect alsa2jack to its inputs so its ready to record from Firefox at boot. -

- -
- -

Creating a LADISH studio

-
- -

-Before you can create a LADISH studio, you need to ensure that you can start JACK OK, ideally without any xruns. If JACK isn't already running then Claudia will try to automatically start JACK using the current JACK settings, which it shares with Cadence, when you start a studio but it will fail if your JACK settings aren't correct. See the previous 'An introduction to Cadence' and 'JACK Configuration' chapters for tips on setting up JACK. -

- -

-Claudia's interface is divided into four main areas when a studio is loaded. The menus and controls are along the top, a studio and room list is displayed to the upper left, a canvas preview on the lower left (when a studio is loaded) then the currently selected studio occupies the rest of Claudia's window. Claudia may automatically create a new studio when you launch it, otherwise the main canvas will be blank save for some instructions to help you get started with creating a studio. As these instructions state, you can create a new LADISH studio by selecting 'New Studio' from Claudia's studio menu. You can call the studio anything you want but I'll just use 'qtractor' for the studio name. -

- -
- -

Start JACK and the ALSA bridge

-
- -

-If you've not already got JACK running, then now is a good time to start it. You can either start JACK from Cadence, choose 'Start Studio' from Claudia's studio menu or push F5 in Claudia. When you do this, you will notice Claudia's transport controls become available and at least two items appear on the studio canvas - the JACK 'Hardware Capture' and 'Hardware Playback' ports. These are only visible in Claudia when the JACK server is running. For the purposes of this example we also need the Cadence ALSA audio bridge to be running. When you have the ALSA audio bridge running you will see an extra two items (JACK clients) in Claudia's studio editing area- alsa2jack, which gets auto-connected to the Hardware Playback ports, and jack2alsa which gets auto-connected to the Hardware capture ports. -

- -
- -

Adding an app to a studio

-
- -

-Now we shall add qtractor into our studio by choosing 'Add New…' from the application menu, selecting qtractor under the DAW tab of the Claudia launcher then choosing OK. This will launch qtractor and add it into our studio. You may want to minimise or move qtractor to a different virtual desktop for the moment if you only have a small display as we are still working within Claudia; where you should now see a new JACK client box for qtractor within the editor as well as a new item, called Qtractor, added to the studio list. -

- -
- -

Making JACK connections

-
- -

-We want this studio to automatically connect the outputs of alsa2jack (which outputs the sound of all non-JACK apps, such as Firefox) into qtractor so we must connect one to the other. Left-click on capture_1 within the alsa2jack box then, keeping the mouse button pressed, drag your pointer over the Master/in_1 input of qtractor, then let go. You should then see a blue line connecting the alsa2jack client to qtractor's input port - this indicates you have created a JACK connection between the two. Now do the same for alsa2jack's capture_2 and qtractor's Master/in_2 so that both the left and right channels will get sent from ALSA to qtractor. Finally, connect qtractor's Master/out_1 and Master/out_2 to the Hardware Playback ports so that you can hear qtractors output. That completes our studio configuration so save the studio, which should look something like this: -

- -

-Simple Claudia Studio example config -

- -
- -

Loading a studio at boot

-
- -

-To set a studio to auto-load at boot, go to the main Cadence window, check that 'Auto-start JACK or LADISH at login' is ticked, and then click on the three dots to the right of this text. Choose 'Load LADISH studio', select the just-created qtractor studio and then push OK. -

- -

-Next time you reboot you should find JACK starts using the settings saved within your studio, qtractor loads automatically and if you open Claudia (or Catia) you should see alsa2jack is connected to qtractor. -

- -
- -


- - diff --git a/Documentation:Manual:useful_links_and_getting_help.php b/Documentation:Manual:useful_links_and_getting_help.php deleted file mode 100644 index 6a87953..0000000 --- a/Documentation:Manual:useful_links_and_getting_help.php +++ /dev/null @@ -1,225 +0,0 @@ - - -
- -
- -

Useful Links

-
- -
- -

KXStudio

-
- -

-For more info on the KXStudio applications such as Cadence, Claudia and Catia -

- -

-http://kxstudio.linuxaudio.org/KXStudio:Applications -

- -
- -

Hardware Compatibility

-
- -

-To check to see if your sound device is supported by GNU/Linux, check the ALSA SoundCard Matrix -

- -

-http://www.alsa-project.org/main/index.php/Matrix:Main -

- -

-If you have a FireWire audio device you will want to check the status of your device in the FFADO Device support database -

- -

-http://www.ffado.org/?q=devicesupport/list -

- -

-Another good resource for GNU/Linux audio hardware compatibility is the linuxaudio.org Current Audio Gear page -

- -

-http://wiki.linuxaudio.org/wiki/current_audio_gear -

- -

-To check for the compatibility of your printer with the GNU/Linux printing system, CUPS, check the OpenPrinting database -

- -

-http://www.openprinting.org/printers -

- -
- -

GNU/Linux software resources

-
- -

-The Ubuntu package archive search -

- -

-http://packages.ubuntu.com/ -

- -

-The linuxaudio.org wiki has a comprehensive list of all GNU/Linux audio and sound software -

- -

-http://wiki.linuxaudio.org/apps/start -

- -

-Libre Graphics World provides news and other resources relating to free graphics software -

- -

-http://libregraphicsworld.org/ -

- -

-Freecode maintains the Web's largest index of GNU/Linux software -

- -

-http://freecode.com/ -

- -

-The Wine Application Database (AppDB) details the compatibility of Windows programs with Wine -

- -

-http://appdb.winehq.org/ -

- -
- -

Recommended tutorials and guides

-
- -

-To get the most out of Linux, you need to understand how to use the terminal (aka console). Here's the Ubuntu beginners guide to using the terminal -

- -

-https://help.ubuntu.com/community/UsingTheTerminal -

- -

-KXStudio uses the KDE Desktop Environment by default. Here is an introduction to the KDE 4 Plasma desktop -

- -

-http://userbase.kde.org/Plasma -

- -

-JACK was created mainly for Ardour which remains the most popular open source DAW. Sadly its not the most intuitive app ever so you may want to read its manual -

- -

-http://manual.ardour.org/ -

- -

-Those who prefer the more lightweight DAW qtractor will be happy to hear it has one of the best free manuals available for a free and open GNU/Linux app -

- -

-http://downloads.sourceforge.net/qtractor/qtractor-0.5.x-user-manual.pdf -

- -
- -

Getting Help

-
- -

-Remember that KXStudio the distribution is based upon Ubuntu 12.04 aka Precise so any instructions or software you find for Ubuntu (precise) will be compatible with KXStudio. -

- -
- -

Fora and wikis

-
- -

-If you get stuck, the first place to search for a solution is on the KXStudio forum -

- -

-http://linuxmusicians.com/viewforum.php?f=47 -

- -

-If you suspect its more of a general Ubuntu issue it would be a good idea to search for help on the Ubuntu fora too -

- -

-http://ubuntuforums.org -

- -

-The LinuxAudio wiki contains all sorts of useful info for Linux audio users, including this manual -

- -

-http://wiki.linuxaudio.org -

- -
- -

IRC

-
- -

-If you can't find an answer to your question on the fora or with your favourite search engine, IRC is going to be your best hope of getting help quickly. -

- -

-KXStudio includes the Konversation KDE IRC client which you can use to connect to the following channels on irc.freenode.net -

- -

-#kxstudio is the official IRC support channel for KXStudio -

- -

-#opensourcemusicians is the IRC channel of the open source musicians podcast -

- -

-#ardour has its own official IRC support channel on freenode.net as do many other popular open source projects -

- -

-#kde is good for general issues with using the K Desktop -

- -

-#ubuntu is the support channel for general Ubuntu system issues -

- -
- -


- - diff --git a/Documentation:Manual:video_drivers.php b/Documentation:Manual:video_drivers.php deleted file mode 100644 index ab02916..0000000 --- a/Documentation:Manual:video_drivers.php +++ /dev/null @@ -1,110 +0,0 @@ - - -
- -

-The majority of modern day PC hardware uses display technology from either Nvidia, ATI/AMD, or Intel. -

- -

-Intel drivers are open source but the official Nvidia and ATI/AMD drivers are proprietary. Fresh KXStudio installations include official drivers for Intel video but only unofficial drivers for Nvidia and ATI/AMD. The official Nvidia or ATI/AMD drivers are easily added if required, and they often provide superior performance (especially for OpenGL 3D and gaming), extra or more complete features, and better power management. -

- -
- -

What type of video hardware do I have?

-
- -

-If you're unsure what vendor or model video hardware you have installed in your machine, open a terminal (such as Konsole) and type: -

-
lspci
- -

-lspci will 'List PCI' hardware installed on your machine, including your video device - the make and model of which is listed as being a 'VGA compatible controller'. If it is a Nvidia or ATI/AMD device then you may want to switch to the non-free driver, if its available for your hardware, to take advantage of the extra features and better performance. -

- -
- -

Using the 'Additional Drivers' tool

-
- -

-The 'Additional Drivers' tool can be used to simplify the process of downloading and installing or removing non-free video drivers. It requires that you are connected to the internet for it to fetch the requested drivers. From the KX Studio desktop menu you can find it under the Applications → System sub-menu or you may find it easier to search for it. -

- -

-When you run the Additional Drivers tool it will check the type of video hardware you have before presenting a new window in which you will see a list of compatible drivers, if any are available. You may be presented with more than one suitable driver but it's safe to use the recommended version if you're unsure which version of the driver is best for you. Select a driver, then click 'Activate' which will then download and install the new driver. The new driver will not take effect until you have rebooted. -

- -
- -

Configure default laptop screen brightness

-
- -

-Lower laptop screen brightness settings conserve energy and increase battery life but sometimes visibility can suffer. A fresh install of KXStudio/Ubuntu defaults to the lowest brightness settings, for my laptop display at least, and I find it uncomfortable on anything other than its highest brightness setting so I set that to be the default at boot by running the command: -

-
kdesudo kate /etc/rc.local
- -

-and adding the line -

-
echo 7 > /sys/class/backlight/acpi_video0/brightness
- -

-somewhere before the line that says 'exit 0'. This command sets the screen brightness to the max value of 7, the lowest brightness setting being 0. The file /sys/class/backlight/acpi_video0/max_brightness tells you what the max setting is. -

- -

-It's important to note that the path to the brightness setting as well as the values used may differ depending on your video hardware. laptop model and display config so you will have to check for the presence of these files and discover their correct locations before modifying rc.local. -

- -
- -

Nvidia video fixes and tweaks

-
- -

-To enable the screen brightness control keys and disable the NVIDIA boot logo on my NVIDIA-using laptop using the non-free nvidia driver I had to create a file located at /usr/share/X11/xorg.conf.d/10-nvidia-brightness.conf so run a command like: -

-
kdesudo kate /usr/share/X11/xorg.conf.d/10-nvidia-brightness.conf
- -

-containing (copy/paste this into that .conf file) -

-
Section "Device"
-  Identifier     "Device0"
-  Driver         "nvidia"
-  VendorName     "NVIDIA Corporation"
-  BoardName      "GeForce 8600M"
-  Option         "RegistryDwords" "EnableBrightnessControl=1"
-  Option "NoLogo" "true"
-EndSection
- -

-Then, after rebooting, I could hold the Fn key and use the up/down arrow keys to adjust my laptop screen brightness. I don't think the VendorName and BoardName matter too much here and this change should work for anyone using the non-free Nvidia driver on a laptop. -

- -
- -

Additional AMD issues

-
- -

-For thorough information about the proprietary AMD drivers, including how to install more up-to-date drivers or how to remove the proprietary drivers and return to the FLOSS ones, see the AMD Linux driver community wiki. -

- -
- -


- - diff --git a/Documentation:Manual:wineasio_and_reaper.php b/Documentation:Manual:wineasio_and_reaper.php deleted file mode 100644 index 653a8e4..0000000 --- a/Documentation:Manual:wineasio_and_reaper.php +++ /dev/null @@ -1,140 +0,0 @@ - - -
- -
- -

What is Wine?

-
- -

-KXStudio includes a program called Wine (Wine Is Not an Emulator) which allows most MS Windows software to run under GNU/Linux. It is FLOSS and does not require a copy of Windows to run. While a number of Windows applications will not run at all under Wine, there is the odd app or game that runs BETTER under Wine than real Windows! In most cases though, MS Windows apps run slower under Wine than under a genuine Windows install. Overall, it is recommended to run native GNU/Linux software instead of using Windows software under Wine, but the option of Wine allows flexibility if no suitable, Linux-native alternative software is available currently for a specific task. -

- -
- -

What is WineASIO?

-
- -

-Audio Stream Input/Output (ASIO) is the most common low-latency sound card driver protocol for MS Windows, hence most professional Windows audio software is designed to work with ASIO. KXStudio includes WineASIO which provides an ASIO to JACK driver for Wine. This allows ASIO-compatible Windows software running under Wine to access your JACK device/server as if it was an ASIO device. -

- -
- -

Configure WineASIO

-
- -

-WineASIO provides various options that can be configured within Cadence. These options are: -

- - -

- -

- -
- -

Registering WineASIO libraries

-
- -

-If you have run KXStudio Welcome Setup previously then you should already have the wineasio.dll library registered. Otherwise, for example if you have messed up or deleted your Wine configuration, you should run: -

-
regsvr32 wineasio.dll
- -

-If you're running a 64-bit OS and you want to run 64-bit Windows software under wine, run the following too: -

-
wine64 regsvr32 wineasio.dll
- -

-You should only need to issue these commands once, if at all, but there is no harm in re-running them. -

- -
- -

What is REAPER?

-
- -

-KXStudio includes the MS Windows version of REAPER (Rapid Environment for Audio Production, Engineering, and Recording). REAPER is proprietary software which runs as a fully-functional demo for trial. It is one of the most powerful and popular DAWs available for Windows and Mac OSX, and a native Linux version is in development. REAPER has proven popular under GNU/Linux due to its advanced audio production features, its not-FLOSS-but-nonetheless-user-friendly licensing and its official support for running the Windows version under Wine. -

- -
- -

Installing REAPER

-
- -

-You can download Reaper from the official website at http://reaper.fm/download.php -

- -

-If you are using a 32-bit system, choose windows installer for reaper 32bits and for a 64 bits, choose windows installer for reaper 64 bits. -

- -

-You can simply install reaper by double clicking on the file you just download and follow the steps shown in the window that should opened. -

- -

-Then be really carefull to NOT CHECK rearoute (ASIO driver) installation. Installing rearoute could result in a conflict with WineASIO. -

- -

-then don't forget to register wine as mentionned in the previsous chapter : Registering WineASIO libraries. -

- -
- -

Configure REAPER for WineASIO and JACK

-
-
    -
  1. Start REAPER then choose Preferences, the bottom option in the Options menu, or just push CTRL+P
    -
  2. -
  3. Choose Device under the Audio section from the list to the left of the Preferences window
    -
  4. -
  5. Choose ASIO from the Audio drop-down menu at the top of the Audio device settings options. You should then see 'WineASIO Driver' is selected as the ASIO driver.
    -
  6. -
  7. Apply, OK, done!
    -
  8. -
- -
- -

REAPER / Claudia (or catia) issue

-
- -

-To prevent some misconfiguration between REAPER and Cadence tools (Claudia or Catia), you have to set REAPER options. -So, in REAPER, go to options > Preferences, then click on Audio (in the left list panel) and uncheck “close audio device when stopped and applicatin is active”. -

- -
- -


- - diff --git a/Documentation:Repository:Meta-Packages.php b/Documentation:Repository:Meta-Packages.php deleted file mode 100755 index 5e75424..0000000 --- a/Documentation:Repository:Meta-Packages.php +++ /dev/null @@ -1,79 +0,0 @@ - - -

- This section describes all the meta-packages available in the KXStudio repositories, splitted by type. -

- -

Meta-Package List

-

- In a tree-like view, the meta-packages are setup like this: -

- - -

Meta-Package Details

-

- The main meta-packages are Audio, Audio-Plugins, Graphics and Video.
- The Audio-Plugins meta-package is also split into plugin categories, for anyone that wants more plugins, but not actually more applications.
-

-

- The 'meta-restricted-extras' is simply a combination of '[k|x]ubuntu-restricted-extras', plus alsa-firmware and linux-firmware-nonfree.
- (In this case, "restricted" means that it can't be installed in Ubuntu by default, but you're safe to do it afterwards). -

-

- The 'meta-wine' includes Wine audio stuff, useful to install if you want to use Windows plugins after installing the KXStudio ISO.
- This includes carla's Windows bridges, dssi-vst, festige, LMMS VST support and WineASIO. -

- -

Notes

-

- The 'meta-all' package recommends 'meta-restricted-extras' and 'meta-audio' recommends 'meta-audio-plugins'.
- Depending on your distro these might be treated as dependencies. -

-

- Audio plugins packages that include several formats (like drumgizmo that includes LV2 and VST) or standalone applications (like calf-plugins) - are not part of the specific 'meta-audio-plugins-*' packages.
- This is because installing those will install additional plugin formats and/or full applications.
- To ensure, for example, that you get all possible LV2 plugins, install 'meta-audio-plugins' and 'meta-audio-plugins-lv2'. -

-

- The 'meta-audio-plugins-collection' package is an alternative to installing all plugins at once.
- If you're the kind of person that only wants to install the best plugins, consider installing this package first before installing other audio meta-packages.
- This way installing 'meta-audio' will not pull 'meta-audio-plugins-ladspa', 'meta-audio-plugins-dssi', etc. -

- -


- - diff --git a/Documentation:Repository:RegisterCommercial.php b/Documentation:Repository:RegisterCommercial.php deleted file mode 100755 index 059aec2..0000000 --- a/Documentation:Repository:RegisterCommercial.php +++ /dev/null @@ -1,34 +0,0 @@ - - -

- This section describes how to activate the non-free software available in KXStudio. -

-

- -
Loomer plugins
-

- All Loomer plugins work the same way.
- Just open the respective plugin GUI you have the license for, click the "Options" button at the top and select "Enter Licence Key...".
- Fill in your license details and you're done ;) -

-

- -
Renoise
-

- Renoise registration is a bit unusual, but fairly easy.
- Once you have renoise installed in KXStudio (via repositories), go to your renoise backstage account and download the latest stable linux tarball that matches your system architecture (32bit or 64bit).
- Unpack it, and copy the 'renoise' binary inside into '/usr/bin/'. The next time you start renoise, it will be registered to your account.
- Warning: Do not run the install script in the tarball! If you really want to do so, please remove the 'renoise' package from your system first. -

- -


- - diff --git a/Documentation:Repository:Upgrade.php b/Documentation:Repository:Upgrade.php deleted file mode 100755 index f0cb9be..0000000 --- a/Documentation:Repository:Upgrade.php +++ /dev/null @@ -1,151 +0,0 @@ - - -

- This section describes how to upgrade from a regular Ubuntu 12.04 install (or variants), to a cool and fresh KXStudio Desktop.
- This method will work *only* in Ubuntu 12.04 based systems. -

-

- KXStudio officially supports KDE4 and partially XFCE (on 12.04/12.10, KXStudio will use UbuntuStudio desktop as base as it uses XFCE).
- You can still install KXStudio if using any other Desktop Environment, but there's no meta-packages for them, and we'll not document the install process here.
- Create a new topic in the forums if you want support for other DEs. -

- -


- -
Step 1 - Enable the repositories
-

- Open up the 'Software Sources' (usually in the System menu), and on the 3rd party separator, add this code:
- ppa:kxstudio-team/kxstudio
- Alternatively, you can run this command, which has the same effect:
- - sudo add-apt-repository ppa:kxstudio-team/kxstudio - -

-

- Next, reload the sources (method depends on the current application), and install the package 'kxstudio-repos'. Then reload the sources again.
- You can do the same thing in the command-line with:
- - sudo apt-get update
- sudo apt-get install kxstudio-repos
- sudo apt-get update -
-

-

- NOTE: If you're running 12.04, it's recommended to also install 'kxstudio-repos-kde49' which will update KDE4 to the stable 4.9.5 version. -

- -


- -
Step 2 - Update the system
-

- Once you've got the repositories set-up, it's time to upgrade the system (ie, update the software, not upgrade to a newer Ubuntu release!). -

-

- Simply use whatever tool your Desktop Environment provides (Ubuntu Software Center, Synaptic, Update Manager, KPackageKit, Muon, etc).
- If you want to use the command-line, or if you just got too many dependency conflicts (can happen if you enabled many PPAs before upgrading to KXStudio), the command is:
- - sudo apt-get dist-upgrade -
- Even though it says 'dist-upgrade', it will not update the Ubuntu version. In this case, 'dist' means something like "resolve conflicts, even if some stuff gets removed".
-

-

- This step will take some time. Some minor questions may appear while the upgrade takes place. -

- -


- -
Step 3 - Install the KXStudio Desktop
-

- After the upgrade, it's time to install the main KXStudio packages.
- Just like you did to install the 'kxstudio-repos' package, now install: -

-

- For KDE4 -> 'kxstudio-desktop-kde4'
- For XFCE -> 'kxstudio-desktop-xfce'
- For other systems install 'kxstudio-desktop-base' and the ubuntu related package, like 'lubuntu-desktop' for LXDE
-

- -


- -
Step 4 - Install the Multimedia Software
-

- This step if almost optional. Here we install the basic software for Audio, Graphics and Video.
- Just like before, it's time to install some new meta-packages. They are available as listed here (following a tree view of dependencies): -

- -

- Install the meta-packages you want just like before (ie, search for the package and click to install, or use in command-line: sudo apt-get install <package-name>)
- See Documentation:Ubuntu:Meta-Packages for a description of these meta-packages.
-

-

- Note - meta-all recommends restricted extras, and audio recommends audio-plugins. -

- -


- -
Step 5 - Install a Kernel (Optional)
-

- This step is optional, and mostly useful for audio production only.
- Installing a kernel in KXStudio couldn't be easier - just install one of these packages: -

- -

- The realtime kernels are only available for 10.04 and 12.04.
- Ubuntu 10.04 uses a 2.6.33 RT kernel and 12.04 uses a 3.2.0 one. -

- -


- -
Step 6 - Reboot and update settings
-

- After all this, it's time to reboot.
- The next time you login, you'll see the KXStudio Welcome Screen to help you update your settings (and maybe the theme too).
- You should also run 'cadence' and change your JACK settings to your preference.
- Finally, just re-login again after updating the settings. -

- -


- -
Step 7 - Enjoy!
-

- Of course, now it's time to enjoy! -

- -


- - diff --git a/Documentation:Wiki.php b/Documentation:Wiki.php deleted file mode 100755 index 20a0018..0000000 --- a/Documentation:Wiki.php +++ /dev/null @@ -1,13 +0,0 @@ - - - - - diff --git a/Donations.php b/Donations.php deleted file mode 100755 index a0997cc..0000000 --- a/Donations.php +++ /dev/null @@ -1,34 +0,0 @@ - - -

- KXStudio is and always will be a free and open-source project to everyone.
- Donations help ensure that developers have the needed enthusiasm and motivation to keep working on the project.
- Just because we're open-source doesn't mean we're allergic to money. ;) -

- -

- The KXStudio project is no longer taking donations. -

- -

- In German law donations count as income and thus have to be taxed.
- It came to the point where it was more expensive for the project to have them rather than not.
- As such, donations have been taken down for now.
- They might come back at a later time, when the (single) KXStudio developer relocates to another country. -

- -

- Thanks for understanding. -

- -


- - diff --git a/DonationsStats.php b/DonationsStats.php deleted file mode 100755 index 0c4917c..0000000 --- a/DonationsStats.php +++ /dev/null @@ -1,107 +0,0 @@ -DB connection failed'; - return; -} - -$amount = 0.0; - -$max_month = 0.0; -$total_year = 0.0; - -$donation_count = 0.0; - -$sql_donations = mysqli_query($db_link, "SELECT * FROM donations WHERE YEAR(dt) = " . $year); - -if (mysqli_num_rows($sql_donations)) { - while ($sql_row = mysqli_fetch_assoc($sql_donations)) { - $amount = $sql_row["amount"]; - $donation_count += 1.0; - if ($amount > $max_month) { - $max_month = $amount; - if ($amount > $GLOBALS['biggest_donation_value']) { - $GLOBALS['biggest_donation_date'] = date("Y-m-d", strtotime($sql_row["dt"])); - $GLOBALS['biggest_donation_value'] = $amount; - } - } - $total_year += $amount; - } -} - -$GLOBALS['total_ever'] += $total_year; - -echo ''; -echo ' ' . $year . ''; -echo ' ' . $donation_count . ''; -echo ' ' . number_format($total_year, 2) . '€'; -if ($donation_count > 0.0) { - echo ' ' . number_format($total_year/$donation_count, 2) . '€'; -} else { - echo ' 0€'; -} -echo ' ' . number_format($total_year/12.0, 2) . '€'; -echo ' ' . number_format($max_month, 2) . '€'; -echo ''; - -} - -?> - -

- KXStudio is and always will be a free and open-source project to everyone.
- Donations help ensure that developers have the needed enthusiasm and motivation to keep working on the project.
- Just because we're open-source doesn't mean we're allergic to money. ;) -

- -

- This page contain statistics regarding donations made to the KXStudio project over time. -

- -
- - - - - - - - - -= "2013"; $year -= 1) { - print_donation_year($year); -} - -?> -
 Year  Donation count  Total received  Average per donation  Average per month  Biggest single donation 
-
- -

- So far the KXStudio project has received € in donations.
- The biggest donation ever made was on , with a value of €.
- Thank you very much for your generosity! -

- -


- - diff --git a/DownloadForced.php b/DownloadForced.php deleted file mode 100644 index 295b5e7..0000000 --- a/DownloadForced.php +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/Downloads.php b/Downloads.php deleted file mode 100644 index 389c974..0000000 --- a/Downloads.php +++ /dev/null @@ -1,96 +0,0 @@ - - - - -


- - - -
- - - -


- - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index cf1ab25..0000000 --- a/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to diff --git a/News.php b/News.php deleted file mode 100644 index f0b7d24..0000000 --- a/News.php +++ /dev/null @@ -1,1901 +0,0 @@ - - -

THIS IS A FAKE PAGE, KXSTUDIO NEWS USES A DYNAMIC MODULE NOW

- -

- > Changes in KXStudio repos, regarding Carla and JACK2
- On 2019-03-22 by falkTX -

-

- This is a small notice to everyone using Carla and JACK2 with the KXStudio repos. -

-

- First, in preparation for Carla 2.0 release, the (really) old carla package is now the new v2.0 series, - while carla-git now contains the development/latest version.
- If you are not interested in testing Carla's new stuff and prefer something known to be more stable, - install the carla package after the latest updates. -

-

- Second, a change in JACK2 code has made it so a restart of the server is required after the update.
- (but for a good reason, as JACK2 is finally getting meta-data support; this update fixes client UUIDs)
- If you use jackdbus (likely with KXStudio stuff), you will need to actually kill it.
- If that does not work, good old restart is your friend. :) -

-

- One important thing to note is that the lmms package now conflicts with the carla-git one.
- This is because some code has changed in latest Carla that makes v2.0 vs development/latest ABI-incompatible.
- In simpler terms, LMMS can only either be compiled against the stable or development version of Carla.
- The obvious choice is to use the stable version, so after the updates if you notice LMMS is missing, just install it again.
- (If you have carla-git installed, carla will be installed/switched automatically) -

-

- I tried to make the transition of these updates as smooth as possible, - but note that you likely need to install updates twice to complete the process.
-

-

- In other news, we got a new domain!^-^)/
- Also Carla v2.0 release date has been set - 15th of April.
- Unless a major issue is found, expect a release announcement on that day.
- See you soon then! ;) -

- -
- -

- > Carla 2.0 RC4 is here!
- On 2019-03-02 by falkTX -

-

- Hello again everyone!
- This is a quick fix for the Carla Plugin Host (soon-to-be) stable series.
-

- -

Changelog

- -

- I am not confident enough to call it the stable version just yet, - as some of these release changes actually introduced new code.
- But the target date for the stable release is now set - middle of April.
- There are no more release-blocker bugs for Carla v2,0 anymore, so it is just a matter of time now.
-

- -

Downloads

-

- To download Carla binaries or source code, jump on over to the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump on over to the Carla's Github project page for those. -

- -
- -

- > DPF-Plugins v1.2 released
- On 2019-03-02 by falkTX -

-

- Hello everyone, a new release of DPF-Plugins is here.
- This is mostly a bugfix release, with a few little new things.
- This is what changed compared to the last release: -

- - -

DPF changes

-

- DPF (the small framework behind these plugins) saw some important changes.
- They are not all relevant to DPF-Plugins directly, but worth mentioning: -

- -

- Other things worth noting is that 2 new exciting things are currently under development: - Cairo graphics support and AU plugin wrapper.
- Eventually these will be part of core DPF, but for now they are being discussed and worked on with other developers. -

- -

Downloads

-

- The source code plus Linux, macOS and Windows binaries can be downloaded at - - https://github.com/DISTRHO/DPF-Plugins/releases/tag/v1.1.
- The plugins are released as LADSPA, DSSI, LV2, VST2 and JACK standalone.
-

- -
- -

- > Carla 2.0 RC3 is here!
- On 2019-01-15 by falkTX -

-

- Hello everyone, happy new year!
- This is a quick fix for the Carla Plugin Host (soon-to-be) stable series.
- Only very small fixes here, and a change on how specific plugins load.
- This release starts a "release early, release often" attitude, that hopefully I can maintain from now on.
-

- -

Changelog

- - -

- Previously a few plugins were hardcoded to run as plugin bridges, as they were deemed unsafe because of how they use their plugin UIs (instance-access).
- Carla automatically started these plugins as bridges, as to not crash the main process when Gtk and Qt gets in the way.
- Plugin state in bridges have a few issues (as plugin bridges are experimental right now), which I was hoping to fix before the final 2.0 is here.
- But that will not happen it seems (not an easy fix), so now these plugins will run normally as all others do, in the same process.
- This means the following possible breaking changes:
-

- -

- This is not an issue for other plugin UIs that use Qt or Gtk, as they do not use LV2 instance-access.
- Carla runs Gtk and Qt LV2 UIs in a separate process, but because these UIs require direct access to the plugin instance, they cannot be bridged.
-

- -

Downloads

-

- To download Carla binaries or source code, jump on over to the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump on over to the Carla's Github project page for those. -

- -

Future

-

- A - - "2.0-final" milestone - is on GitHub, which lists the remaining issues to be fixed before 2.0 is considered "final".
- New features already made its way to Carla, but sit on the - - develop branch.
- When the "final" version is released, expect a 2.1-beta to come shortly afterwards. -

- -
- -

- > JackAss v1.1 release
- On 2019-01-15 by falkTX -

-

- This is a tiny bugfix for JackAss, a VST plugin that provides JACK-MIDI support for VST hosts.
-

-

- The only change is that Wine 64bit builds work now, so you can finally load it inside 64bit Windows applications running on GNU/Linux via Wine.
- Tested to work with FL Studio 20.
-
-

-

- You can find JackAss source code and bug tracker in Github, - at https://github.com/falkTX/JackAss/. -

- -
- -

- > Carla 2.0 RC2 is here!
- On 2018-10-27 by falkTX -

-

- Hello everyone, this is the announcement for a Carla stable update.
- Only 2 blocking issues remain, 1 of which needs testing to see if it still happens or not.
-

- -

General fixes

- - -

Usability fixes

- - -

Downloads

-

- To download Carla binaries or source code, jump on over to the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump on over to the Carla's Github project page for those. -

- -

Future

-

- Work for KXStudio 18.04 ISO is under way, should only take a few more weeks now.
- Next JACK2 release will be quite nice, we have meta-data now (thanks to Rui), - but that will be handled after KXStudio 18.04 ISO release. -

- -
- -

- > Carla 2.0 RC1 is here!
- On 2018-09-16 by falkTX -

-

- Hello again everyone, and surprise, the stable 2.0 version of Carla is coming!
-

-

- This is the announcement of the first release candidate of Carla 2.0.
- Very little features were added, focus went on stability instead.
- The 'master' branch on Carla's source code is now for stable content, all new stuff will go to 'develop'.
- My intention is to really let Carla on the side for now. If I can do it or not remains to be seen...
-

-

- The list of changes is a little big, so let's split it by parts.
- First, the highlights and major changes.
-

- -

Highlights and major changes

-
LinuxSampler removed, replaced by SFZero
-

- Basically I removed the code that interacted internally with LinuxSampler, and replaced it by SFZero.
- There are a lot of reasons for this change, but we can resume it to 3 points:
-

- -

-

- Removing LinuxSampler means we lose support for GIG files, also SFZero loads the entire kit in RAM.
- But, in return, SFZ files now always load without getting muted or having to do dirty workarounds.
- Plus, with this, Carla can keep SFZ support while maintaining its GPLv2 license intact.
-

-

- Note that SFZero does not support some opcodes, so the playback might sound different.
- At a later date, a release will be made that will focus on SFZ support.
-

- -
Big windows fixes
-

- Carla under has always a been a bit behind, compared to its Linux and macOS support.
- Not anymore!
-

-

- Carla can now run as a plugin in Windows, and also the PyQt-based big-meter, midi-pattern and notes plugins.
- With this done, Carla as LV2 is now included in the Windows builds.
-

-

- The export of a single plugin as LV2, though it is an experimental feature, now also works on Windows.
- Because Windows does not handle symlinks very well, Carla copies its resources instead.
-

-

- Scanning plugins will no longer show a console window.
- The font engine was changed from native to freetype, which not only fixes the mini-canvas but gives a better presentation too.
- Plugin bridges work once again, and now even better as Carla now initializes Windows resources on them (like static pthread and OLE).
-

- -
UI changes
-

- The piano-keyboard widget got some attention, now has 4 different highlight colors, 3 input layouts (qwerty, qwertz and azerty) and allows to change the offset when using the PC keyboard to send notes.
- Just right-click on a piano-keyboard widget to trigger these options.
-

-

- The rack looks a bit different now, as the possible "skins" for the plugin slots are now exposed and can be changed at any time.
- You can change the background color too. Because why not? :)
-

-

- Make the knobs and rack buttons more white-theme friendly.
- This was needed to get white backgrounds working correctly, so for those of you that prefer Carla in a more bright theme, it will behave better now (why would you do that though?)
-

- -

Other changes

-

- Some changes that make sense or are useful enough, and that deserve to be mentioned.
-

- - -

Fixes

-

- Besides the ones already mentioned for Windows, we also have: -

- - -

Notes for developers and packagers

- -

- Currently work-in-progress is a complete REST API of Carla's backend, allowing to have full control of a remote Carla instance.
- (and not in a limited fashion like done with Carla-Control / OSC).
- Initial code for it is already done, and tested to work.
- If this interests you, let me know!
-

-

-

- -

Notes for users

-

- The code for scanning plugins had a little rework, making some internal data structures change.
- Because of this, a full rescan of your plugins is needed after the update.
-

-

- When running Patchbay mode in JACK, changing the buffer size might cause a crash.
- This is not a common action to do, so not a priority to fix.
-

- -

Downloads

-

- To download Carla binaries or source code, jump on over to the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump on over to the Carla's Github project page for those. -

- -

Future

-

- With Carla done, next up is DPF handling and KXStudio 18.04 ISO release, while trying to get a new JACK2 release out too.
- Note that after these 3 items are done, I plan to take a well-needed break from open-source project maintenance. -

- -
- -

- > Carla 2.0 beta7 is here!
- On 2018-07-23 by falkTX -

-

- Hello again everyone, I am glad to bring you the 7th beta of the upcoming Carla 2.0 release.
- Last time I said beta6 would be the last beta, but let's ignore that for now... ;)
-

-

- This release focuses on bug-fixes rather than new features.
- Most of the new features were added because of contributions, which are very appreciated.
- There are no big flashy screenshots this time, sorry.
-

-

- One breaking change for this release is the removal of most of the plugins bundled in Carla's code.
- They were moved into a separate repository, to keep Carla's code-base smaller.
- If you are building Carla yourself and you want those extra internal plugins, make sure to enable git submodules. -

-

- Here is a list of the most relevant changes and fixes for this release: -

- - -

Downloads

-

- To download Carla binaries or source code, jump on over to the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump on over to the Carla's Github project page for those. -

- -

Future

-

- The next Carla release is meant to close the 2.0 features, and focus on feature parity between all OSes.
- It might take some time though (unless there is major regression that makes a new release required). -

-

- For now I plan to focus on other things that have been on the backlog for some time, - including DPF, KXStudio 18.04 ISO and JACK maintenance.
- News on that will be published when something is ready, please be patient. -

- -
- -

- > Cadence 0.9.0 release and KXStudio 18.04 preparations
- On 2018-04-02 by falkTX -

-

- Cadence 0.9.0 has just been tagged in its - git repository.
- No new features have been added to the code-base.
- The release is focused on the Qt5 port, and of course the fixes that have been added over time.
- Qt4 is no longer supported; the code was updated to work with Qt5, without having a fallback Qt4 mode (unlike Carla).
- Cadence Qt5 port is needed for a proper KXStudio 18.04 release, as we will be using KDE5 Plasma as desktop environment.
-

-

- The - KXStudio "Welcome" wizard - has also been ported to Qt5.
- This finalizes the Qt4 => Qt5 porting process, with all KXStudio tools now running in Qt5.
-

-

- In other news, the preparations for KXStudio's 18.04 ISO release - have started.
- The decision is to use - Neon - as the base distro for the next ISO images, with Breezy-Dark as default theme.
- The KXStudio configuration files have been ported from KDE4 to KDE5, with only a few tweaks missing now.
- If you're running the KXStudio repositories with Neon 16.04, you can already install the kxstudio-desktop-neon package. :)
-

-

- Note that Ubuntu 18.04 (and thus Neon 18.04) is not out yet, so a release will of course have to wait for them first.
- (Neon does not actually have their 18.04 repositories fully ready at this point)
- We will have beta images first, to let users test and give feedback.
- When everything seems to run fine, and I am happy with the results, the final image will released.
- No estimation on the 'when' just yet though - it will be out when it's ready - so please don't keep asking. ;)
-

- -
- -

- > Carla 2.0 beta6 is here!
- On 2018-01-25 by falkTX -

-

- Hello again everyone, I am glad to bring you the 6th beta of the upcoming Carla 2.0 release.
- It has been over one year since the last Carla release, it was about time. :)
- This should be the last beta for the 2.0 series, as next one is planned to be release candidate 1. -

-

- There were quite some changes under the hood, mostly in a good way.
- The trade-off for users is that this means losing some features, the biggest ones being VST3 and AU plugin support.
- The way audio and MIDI devices are handled on Windows and macOS also changed, no longer having dynamic MIDI ports.
- See the previous post about Carla to get more details on the "breaking changes". -

-

- But let's move on with the good stuff!
- Here are some of the highlights for this release: -

- -
-transport - -

Transport controls and Ableton Link support (experimental)

-

- Previous releases of Carla had basic time controls already, - but it was quite basic and lacked options for JACK transport and BPM control.
- Now JACK transport is optional, transport works for non-JACK drivers and BPM can be adjusted manually.
- Ableton Link support was added in was well, as another way to sync transport. It was not extensively tested though.
- Also note that, due to compiler support, the current Carla macOS builds do not support Link.
-

-

- Transport can misbehave when rolling back or forwards, so this feature is still classified as experimental.
- The plan is to have transport stabilized when the final 2.0 version is released.
-

-
- -


- -
- - settings - - -

Tweak of settings page

-

- Carla's settings dialog received an overhaul.
- Everything that was deemed unstable was moved into a new 'experimental' page, and disabled by default.
- So in order to use plugin bridges for example, you need to first enable experimental features, then the bridges.
- The (experimental) features mentioned on this article all have to be enabled in the same way too.
- Last but not least, a page dedicated to Wine settings (wine-prefix, wine startup binary, RT variables) was added.
-

-
- -


- -
- - jack-apps - - -

Load of JACK applications as plugins (Linux only, experimental)

-

- This is a big one... :)
- Initially just an idea that became an ugly hack/test for private use only, I soon realized it had great potential.
- So I split the code used for plugin bridges and made it more generic so it could be re-used for such features.
- And here we have it, JACK applications running as regular plugins inside Carla - including showing/hiding their main interface.
- Applications also receive JACK transport as rolling in the host.
-

-

- In this mode Carla basically becomes a self-contained JACK server, and exposes a special libjack to the client.
- The client connects to Carla believing it's actually connecting to "JACK", as Carla implements libjack API through its plugin bridge mechanism.
- Within Carla you first define a fixed number of audio and midi ports at the start.
- Ports are allocated dynamically on the plugin side, but get mixed down at the end to the number of outputs selected.
- This is a nice workaround against clients that dynamically register their ports, sometimes with random names too.
- With Carla jack-apps-as-plugins method, the client ports are persistent.
-

-

- The full libjack API is not implemented though, only the important parts, in order to get most applications running.
- The most notable missing calls are related precise timing information and non-callback based processing.
- Also no session management is implemented at the moment.
- But, even without this, stuff like audacity, lmms, hydrogen, renoise and vlc work.
-

-

- This is a work in progress, but already working quite well considering how new it is.
-

-
- -


- -
- - export-lv2 - - -

Export any loaded plugin or file as a single LV2 plugin (experimental)

-

- Another big feature of this release is the possibility to export any plugin or sound file loaded in Carla - as its own self-contained (LV2) plugin.
- This can really be any regular plugin, a sound bank (e.g. an SFZ file), a plugin bridge or even JACK application.
- The exported plugin will run with the smallest amount of wrapping possible between the host and the carla loaded plugin.
- Carla will not appear at all, triggering the "show ui" on the host will show the actual plugin UI.
- ***Note that the exported plugins are not portable! They require Carla to be always installed on the same location.***
-

-

- Audio, MIDI, transport information, custom UI are fully working already.
- The only missing feature at the moment is LV2 state, which needs to map to DSSI configures, VST chunks and other stuff.
- Although working for non-Linux systems, this was not tested.
- Testing of this feature in general is very appreciated.
-

-
- -


- -
- - freebsd - - -

FreeBSD and other non-Linux systems

-

- After the removal of the juce library from the code-base (as - - discussed before), - Carla was free to support more than just the big 3 OSes.
- With the help of the community, Carla is now available to install on FreeBSD through its ports system.
- I was able to build and install it myself as well, and actually make good noise on a BSD system. Neat! :)
- It's also now possible to build Carla for GNU/Hurd and HaikuOS as well, and I imagine for even more systems if one so desires.
- If this is something you're interested in and need some help, let me know. -

-
- -


- -

Other changes

-

- There are quite a lot of other smaller changes made in Carla since beta5, these include:
-

- - -

Special Notes

- - -

Downloads

-

- To download Carla binaries or source code, jump on over to the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump on over to the Carla's Github project page for those. -

- -
- -

- > JACK2 1.9.12 release and future plans
- On 2017-12-21 by falkTX -

-

- A few days ago a new version of JACK2 was released.
- You can grab the latest release source code at - - https://github.com/jackaudio/jack2/releases.
- The official changelog is:
-

- -

- If you did not know already, I am now maintaining JACK2 (and also JACK1).
- So this latest release was brought to you by yours truly. ;)
-

-

- The release was actually already tagged on the git repo quite some time ago, but I was waiting to see if Windows builds were possible.
- I got side-tracked with other things and 1.9.12 ended up not being released for some time, until someone reminded me of it again... :)
- There are still no updated macOS or Windows builds, but I did not want to delay the release further because of it.
- The 1.9.11 release (without RC label) was skipped to avoid confusion with the versions.
- So 1.9.12 is the latest release as of today. macOS and Windows binaries still use an older 1.9.11 version. -

-

- Being the maintainer of both JACK1 and JACK2 means I can (more or less) decide the future of JACK.
- I believe a lot of people are interested to know the current plan.
-

-

- First, JACK1 is in bug-fix mode only.
- I want to keep it as the go-to reference implementation of JACK, but not add any new features to it.
- The reason for this is to try to get JACK1 and JACK2 to share as much code as possible.
- Currently JACK2 includes its own copy of JACK headers, examples and utilities, while JACK1 uses sub-repositories.
- During the course of next year (that is, 2018) I want to get JACK2 to slowly use the same stuff JACK1 does, then switch to use the same repositories as submodules like JACK1 does.
- This will reduce the differences between the 2 implementations, and make it a lot easier to contribute to the examples and utilities provided by JACK.
- (Not to mention the confusion caused by having utilities that work in simlar yet different ways)
- We will keep JACK1 "frozen" until this is all done.
-

-

- Second, but not least important, is to get the JACK1 specific features into JACK2.
- A few things were added into JACK1 after JACk2 was created, that never made it into JACK2.
- This includes meta-data (JACK2 does have the API, but a non-functional one) and the new internal clients.
- The purpose is to reduce reasons users might have to switch/decide between JACK1 and JACK2.
- JACK2 should have all features that JACK1 has, so that most users choose JACK2.
-

-

- Now, you are probably getting the impression that the focus will be on JACK2, which is correct.
- Though I realize some developers might prefer JACK1's design, the long "battle" of JACK1 and JACK2 needs to stop.
- Development of new features will happen in the JACK2 codebase, and JACK1 will slowly become legacy.
- Well, this is my personal plan at least.
-

-

- Not sure if this all can be done in 2018, but better to take things slowly and get things done than do nothing at all.
- I will keep you updated on the progress through-out the year.
- Happy holidays everyone!
-

- -
- -

- > Breaking changes in Carla Plugin Host
- On 2017-11-21 by falkTX -

-

- Hello everyone, I have some bad and good news about Carla.
- If you've been following the development on the git repository you likely know what this is about.
- There were some major changes done to Carla's code base in the past few days.
-

-

- The biggest change is the removal of the Juce library.
- The reasons for this are well known by some developers, but I'll not write about them here.
- After looking around for alternatives, - I decided to fork an older GPLv2 compatible version of Juce and strip it down to the really essential parts needed - to get Carla to build and run - even if it meant losing some of the features.
- The possibility to change to an entirely different C++ framework crossed my mind, - but the amount of effort and breaking changes would be too big.
- I called the end result 'water'. You can say Carla doesn't need Juce, water is fine ;)
- There's only a few classes and files needed for I/O, XML and AudioGraph handling, everything else is gone. \o/ -

-

- The implications for this change are not big for Linux users, - and is even a source of good news for other OpenSource Operating System users like FreeBSD and HaikuOS.
- In short, because Juce is no longer there, we have lost support for VST3 and AudioUnit plugins.
- Plus VST2 plugins on Windows and MacOS are now handled by Carla's code instead of relying on Juce.
- This heavily reduces the amount of compatible plugins handled by Carla, because Juce had a lot of hacks in order - to make a lot of commercial plugins run properly.
- Also Carla on Windows and MacOS used Juce to handle Audio and MIDI devices, - which now has been changed to RtAudio and RtMidi.
- RtAudio & RtMidi are not as fully-featured as Juce was (we lose dynamic MIDI ports, for example), - but I am glad to have Juce gone from the code-base.
- (You can say that parts of it are still there, but my conscience is clear, - and Carla remains self-contained which was my main point since v2.0 development started) -

-

- The next breaking change relates to the internal plugins used in Carla.
- The plugins that already exist as LV2 will stop being exported with the carla.lv2 bundle.
- Plus these plugins will soon be removed from the default build.
- They quickly bloat the Carla binaries, as they include their artwork. - Not to mention increasing the clone and building times.
- The plan is to have them disabled by default and moved into a new repository as submodule.
- Oh and the "experimental" plugins are going away soon. - It was a mistake to make them Carla-specific in the first place, they should be regular audio plugins instead. -

- Another breaking change is the removal of modgui support.
- The code only worked for PyQt4, which is no longer the default for Carla source-based builds.
- Plus it required webkit, which brings a big list of dependencies. - I would have to port the code to webengine/chromium to make it work with PyQt5... no thanks.
-

-

- The final breaking change is the introduction of the Experimental option in Carla's settings.
- Everything that is not stable at the moment went there as an option, and got disabled by default. This includes: -

- -

- All new in-development / testing features will get introduced as experimental first.
- This will speed up the release of 2.0, since not everything needs to be finished for it.
- For example, plugin bridges can still be there and not fully implemented, and we still have 2.0-stable out! -

-

- That's it! Thanks for reading so far.
- In other news, I gave a small presentation about Carla in this year's Sonoj Conference.
- You can check it out here:
- - https://media.ccc.de/v/sonoj2017-1704-carla-plugin-host - -

-

- Carla 2.0-beta6 will be out soon :) -

- -
- -

- > DPF-Plugins v1.1 released
- On 2017-06-17 by falkTX -

-

- With some minor things finally done and all reported bugs squashed, it's time to tag a new release of DPF-Plugins.
- - - -

-

- The initial 1.0 version was not really advertised/publicized before, as there were still a few things I wanted done first - - but they were already usable as-is.
- The base framework used by these plugins (DPF) will get some deep changes soon, so better to have this release out now. -

-

- I will not write a changelog here, it was just many small changes here and there for all the plugins since v1.0.
- Just think of this release as the initial one. :P -

-

- The source code plus Linux, macOS and Windows binaries can be downloaded at - - https://github.com/DISTRHO/DPF-Plugins/releases/tag/v1.1.
- The plugins are released as LADSPA, DSSI, LV2, VST2 and JACK standalone.
-

-

- As this is the first time I show off the plugins like this, let's go through them a little bit...
- The order shown is more or less the order in which they were made.
- Note that most plugins here were made/ported as a learning exercise, so not everything is new.
- Many thanks to António Saraiva for the design of some of these interfaces! -

- -

Mini-Series

-

- This is a collection of small but useful plugins, based on the good old LOSER-Dev Plugins.
- This collection currently includes 3 Band EQ, 3 Band Splitter and Ping Pong Pan.
-
- 3bandeq - 3bandsplitter - pingpongpan -

- -

MVerb

-

- Studio quality, open-source reverb.
- Its release was intended to provide a practical demonstration of Dattorro’s figure-of-eight reverb structure and provide the open source community with a high quality reverb.
- This is a DPF'ied build of the original - MVerb - plugin, allowing a proper Linux version with UI.
-
- mverb -

- -

Nekobi

-

- Simple single-oscillator synth based on the Roland TB-303.
- This is a DPF'ied build of the - nekobee - project, allowing LV2 and VST builds of the plugin, plus a nicer UI with a simple cat animation. ;)
-
- nekobi -

- -

Kars

-

- Simple karplus-strong plucked string synth.
- This is a DPF'ied build of the karplong DSSI example synth, written by Chris Cannam.
- It implements the basic Karplus-Strong plucked-string synthesis algorithm (Kevin Karplus & Alex Strong, "Digital Synthesis of Plucked-String and Drum Timbres", Computer Music Journal 1983).
-
- kars -

- -

ndc-Plugs

-

- DPF'ied ports of some plugins from Niall Moody.
- See - http://www.niallmoody.com/ndcplugs/plugins.htm - for the original author's page.
- This collection currently includes Amplitude Imposer, Cycle Shifter and Soul Force plugins.
-
- amplitudeimposer - cycleshifter - soulforce -

- -

ProM

-

- projectM is an awesome music visualizer.
- This plugin makes it work as an audio plugin (LV2 and VST).
- prom -

- -

glBars

-

- This is an OpenGL bars visualization plugin (as seen in XMMS and XBMC/Kodi).
- Adapted from the - jack_glbars - project by Nedko Arnaudov.
- glbars -

- -
- -

- > KXStudio 14.04.5 release and future plans
- On 2017-06-10 by falkTX -

-

- Hello there, it's time for another KXStudio ISO release! KXStudio 14.04.5 is here!
-

-

- Lots have changed in the applications and plugins for Linux Audio (even in KXStudio itself), so it was about time to see those ISO images updated.
- Behind the scenes, from what the user can see, it might appear as nothing has truly changed. After all, this is an updated image still based on Ubuntu 14.04, like those from 2 years ago.
- But we had a really big amount of releases for our beloved software, enough to deserve this small ISO update.
- There is no list of changes this time, sorry. The main thing worth mentioning is that base system is exactly the same, with only applications and plugins updated.
- You know the saying - if ain't broken, don't fix it! -

-

- Before you ask.. no, there won't be a 16.04 based ISO release.
- When 2016 started KDE5 was not in a good enough shape, and it would need a lot of work (and time) to port all the changes made for KDE4 into KDE5.
- KDE5 is a lot better now than it used to be, but we missed the opportunity there. -

-

- The current plan is to slowly migrate everything we have into KDE5 (meta-packages, scripts, tweaks, artwork, etc) and do a new ISO release in May 2018.
- (Yes, this means using Ubuntu 18.04 as base)
- The choice of KDE Plasma as desktop environment is not set in stone, other (lighter) desktops have appeared recently that will be considered.
- In the end it depends if it will be stable and good enough for audio production. -

-

- You can download the new ISOs on the KXStudio website, at http://kxstudio.linuxaudio.org/Downloads#LiveDVD.
-

-

- And that's it for now.
- We hope you enjoy KXStudio, being it the ISO "distribution" release or the repositories. -

- -
- -

- > Carla 2.0 beta5 is here!
- On 2017-01-05 by falkTX -

-

- Hello again everyone, we're glad to bring you the 5th beta of the upcoming Carla 2.0 release.
- It has been more than 1 year since the last Carla release, this release fixes things that got broken in the mean time and continues the work towards Carla's 2.0 base features.
- There's quite a lot of changes under the hood, mostly bugfixes and minor but useful additions.
- With that being said, here are some of the highlights: -

- -
-carla-control - -

Carla-Control is back!

-

- Carla-Control is an application to remotely control a Carla instance via network, using OSC messages.
- It stopped working shortly after Carla's move to 2.x development, but now it's back, and working a lot better.
- Currently works on Linux and Mac OS. -

-
- -


- -
-logs-tab - -

Logs tab

-

- This was also something that was brought back in this release.
- It was initially removed from the 2.x series because it did not work so well.
- Now the code has been fixed up and brought to life. -

-

- You can disable it in the settings if you prefer your messages to go to the console as usual.
- Sadly this does not work on Windows just yet, only for Linux and Mac OS.
- But for Windows a Debug/Carla.exe file is included in this build (after you extract the exe as zip file), which can be used to see the console window. -

-
- -


- -
-midi-pattern - -

MIDI Sequencer is dead, long live MIDI Pattern!

-

- The internal MIDI Sequencer plugin was renamed to MIDI Pattern, and received some needed attention.
- Some menu actions and parameters were added, to make it more intuitive to use.
- It's now exported as part of the Carla-LV2 plugins package, and available for Linux and Mac OS. -

-
- -


- -

More stuff

- -

- There will still be 1 more beta release before going for a release candidate, so expect more cool stuff soon!
-

- -

Special Notes

- - -

Downloads

-

- To download Carla binaries or source code, jump into the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump into the Carla's Github project page for those. -

- -
- -

- > Changes in KXStudio repositories
- On 2016-05-06 by falkTX -

- -

- Hey everyone, just a small heads up about the KXStudio repositories. -

- -

- If you use Debian Testing or the new Ubuntu 16.04 you probably saw some warnings regarding weak SHA1 keys when checking for updates.
- We're aware of this issue and a fix is coming soon, but it will require some changes in the repositories.
-

- -

- First, we'll get rid of the 'lucid' builds and rebuild all of them in the 'trusty' series.
- For those of you that were using Debian 6 or something older than Ubuntu 14.04, the repositories will stop working for you later this month. -

- -

- Second, the gcc5 specific packages will be migrated from 'wily' series to 'xenial'.
- This means you'll no longer be able to use the KXStudio repositories if you're running Ubuntu 15.10.
- If that's the case for you, please update to 16.04 as soon as possible. Note that 15.10 will be officially end-of-life in 2 months. -

- -

- And finally, the gcc5 packages will begin using Qt5 instead of Qt4 for some applications.
- This will include Carla, Qtractor and the v1 series plugins.
- Hopefully this won't break anything, but if it does please let us know. -

- -

- That's it for now. Have a nice weekend! -

- -
- -

- > KXStudio Website has moved
- On 2015-07-25 by falkTX -

- -

- Hey all, -

- -

- As you might have noticed sourceforge has been out of service for a while now.
- That, coupled together with the previous adware/spyware fiasco led to me look for alternatives. -

- -

- So you can now find the KXStudio website at http://kxstudio.linuxaudio.org/. -

- -
- -

- > Carla 2.0 beta4 is here!
- On 2015-03-12 by falkTX -

-

- Hello again everyone, we're glad to bring you the 4th beta of the upcoming Carla 2.0 release.
- This release is mostly focused on bug-fixing, so there aren't many splashy new features to show compared to previous ones.
- Still, here's the highlights: -

- -

Highlights

- -
-updated-skins - -

Updated plugin skins

-

- The plugin skins received some updates once again.
- They can now be collapsed in order to take less space.
- More to come soon.
-

-
- -


- -
-experimental-plugins - -

New experimental plugins

-

- Some of the best linux-standalone tools are now working as internal Carla plugins.
- And because Carla exports its internal plugins as LV2, you'll also get them as LV2.
- Note that this is still experimental!
- Also, there's no support whatsoever from the original authors...
-

-
- -


- -
-mod-guis - -

MOD GUI Support

-

- Carla can now show LV2 MOD GUIs, handled like a regular LV2 UI type.
- Note that this only works on the right setups (you need MOD-UI to be working first).
- It's not available on pre-compiled binaries, but you can get it via the KXStudio repositories.
-

-
- -


- -

More changes

- - - -

Special Notes

- - -

Downloads

-

- To download Carla binaries or source code, jump into the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" instead (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump into the Carla's GitHub project page for those. -

- -
- -

- > Carla 2.0 beta3 is here!
- On 2014-10-24 by falkTX -

-

- Hello again everyone, we're glad to bring to you the 3rd beta of the upcoming Carla 2.0 release.
- There have been quite a few nice features implemented since beta2; here are the highlights. -

- -

Highlights

- -
-internal-patchbay - -

Internal Patchbay

-

- This new engine processing mode is similar to what JACK does for all clients and what other modular applications do.
- Every plugin gets its own canvas group and ports allowing you to interconnect plugin audio and MIDI.
- You can use this mode to build complex plugin routing scenarios, perhaps involving several layers of rack and patchbays.
-
- Note that this is currently not available for non-JACK drivers; but for those you can use the internal carla-patchbay plugin.
- There's no support for LV2 Control-Voltage ports as of yet, this will be implemented in the next beta together with MIDI-OSC.

-

-
- -


- -
-new-look - -

Carla as VST plugin (Linux only)

-

- With the first beta of Carla 2.0 we introduced Carla as a plugin, which worked as both internal and LV2.
- Now Carla is available as a VST plugin too, allowing you to load it all DAWs released for Linux.
- There are 4 variants: Rack-Synth, Rack-FX, Patchbay-Synth and Patchbay-FX.
-

-
- -


- -
-lmms-plugin - -

Carla LMMS Plugin

-

- Carla has an LMMS plugin too, as Carla-Patchbay and Carla-Rack instruments.
- So finally you can use native softsynths within LMMS!
- The carla-lmms plugin code is already in LMMS and will be part of its 1.1 release.
-
- If you're using the KXStudio repositories and feel like giving it a try simply install carla-git and lmms.
-

-
- -


- -
-au-plugins - -

AU Plugins (MacOS only)

-

- AU plugins are working in Carla now.
- Carla's plugin compatibility increases once more.
-

-
- -


- -
-updated-skins - -

New and updated skins

-

- There's a new OpenAV-style plugin slot skin.
- Calf and ZynFX have been updated.
- More to come soon.
-

-
- -


- -
-no-skins - -

Old non-skin mode

-

- You can now use the old non-skin mode from Carla 1.x series.
- This saves space if you load lots of plugins at once.
-

-
- -


- -

More stuff

- -

- There will still be 1 or 2 more beta releases before going for a release candidate, so expect more cool stuff soon!
-

- -

Downloads

-

- To download Carla binaries or source code, jump into the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" instead (plus "carla-lv2" and "carla-vst" if you're so inclined).
- Bug reports and feature requests are welcome! Jump into the Carla's Github project page for those. -

- -
- -

- > DISTRHO: New plugins and minor fixing
- On 2014-08-26 by falkTX -

-

In this release we bring 4 new Linux plugin ports:
- - EasySSP
- - LUFS Meter
- - Luftikus
- - Stereo Source Separator
- (Go to http://distrho.sourceforge.net/ports to see the current list of Linux ports.) -

-

The DPF-based plugins also had some minor fixes:
- - 3BandEQ/Splitter had its sliders inverted, now fixed
- - ProM now has pre-compiled linux binaries; UI can be resized by using - and + keys
- - MVerb knobs order has been fixed
- - Allow to open UI in LV2 hosts that don't support options feature (Ingen)
- - Workaround for some VST hosts that don't set sample rate during init (Ardour3 and energyXT)
-

- -
- -

- > The 2nd beta of Carla 2.0 is here!
- On 2014-08-15 by falkTX -

-

- The Carla Plugin Host 2.0 beta2 release is finally here!
- This release was slightly delayed in order to ensure plugin bridges were working properly.
- If you haven't heard about the Carla 2.x series do so here. -

-

- In short, this release makes plugin bridges actually work and it's the first to support MacOS (>= 10.6).
- The backend is now completely toolkit agnostic, only depending on the native window system (like X11 on Linux).
- This release is much more stable when compared to the previous beta - it will no longer eat your cat! ;)
- It should already be good enough for regular usage, if you can ignore some incomplete UI things. -

-

- Known issues / Release notes: (all to be fixed in the next beta) -

- -

- The next beta will change a few things, specially UI-wise.
- The discovery mechanism needs to be reworked for AU support and faster LV2 access.
- Adding plugins and browsing presets will probably change too.
- LMMS and VST plugin versions of Carla-Rack are also planned, but no promises for these.
- We'll be posting more news as things are developed. -

- -
- -

- > DISTRHO New release pack (2014-07-16)
- On 2014-07-16 by falkTX -

-

- DISTRHO has a new release! -

-

- In this release we cleaned up all the plugins, added new ones and removed those that we not considered good enough.
- Standalones are no longer available. Highlife was removed as a requested by its authors. -

-

- The plugins we added to Ports are: -

- -

- Additionally we made a new plugin - ProM - - a music visualizer as audio plugin based on projectm. -

-

- See the plugins and ports sections on - DISTRHO's website for screenshots and downloads.
- The complete source code is available at https://github.com/DISTRHO/. -

- -
- -

- > Introducing JackAss
- On 2014-05-16 by falkTX -

-

- JackAss is a VST plugin that provides JACK-MIDI support for VST hosts.
- Simply load the plugin in your favourite host to get a JACK-MIDI port.
- Each new plugin instance creates a new MIDI port.
-

-

- Here's JackAss loaded in FL Studio:

-

-
- And an example setup in Carla for it:

-

-

-

- JackAss sends the notes from the host to its JACK-MIDI port.
- It also exposes 50 parameters, which send a MIDI CC message when changed.
- You can use this to easily control external applications that accept JACK-MIDI input and possibly CC for automation (like Carla).
-

-

- Additionally there's a JackAssFX plugin, which only exposes parameters to send as MIDI CC, in case you don't need MIDI/notes.
-

-

- JackAss currently has builds for Linux, MacOS and Windows, all 32bit and 64bit. Just follow - this link.
- As a bonus, you also get special Wine builds - load it in a Windows application running in Linux via Wine and you get a real, native JACK-MIDI port from it!
-

-

- You can find JackAss source code and bug tracker in Github: https://github.com/falkTX/JackAss/.
-

-

- PS: Why JackAss? Because it outputs to JACK. ;) -

- -
- -

- > The first Carla 2.0 beta is here!
- On 2014-04-22 by falkTX -

-

- Carla 2.0 is a full rework of the first Carla release.
- It's currently under development with a planned release later this year.
- Today the first beta is released, and we'll show you what to expect when the final version arrives.
-

-

- To download binaries or source code, jump into the KXStudio downloads section.
- If you're using the KXStudio repositories, you can simply install "carla-git" and "carla-plugins-lv2" instead.
- Bug reports and feature requests are welcome! Jump into the Carla's Github project page for those. -

-

- DISCLAIMER: This is a beta release! Although all features mentioned here are working right now, they may be incomplete, have bugs or even eat your cat!
- You've been warned.
-

- -

Highlights

- -
-new-look - -

Canvas Integration

-

- When using the JACK multi-client mode, plugins will be mapped to their respective canvas group.
- Double-clicking the plugin group will show its UI, while pressing 'delete' will remove the actual plugin.
- There's extra right-click options, and the keyboard and meters will react accordingly.
-

-
- -


- -
-new-look - -

New Look

-

- Each plugin gets its own slot skin.
- Different colors are attributed to each kind of plugin (EQ, delay, distortion, etc).
- Specialized skins that match the author/maker are used when appropriate.
-

-
- -


- -
-new-look - -

Carla-Rack as a Plugin

-

- Carla itself working as a plugin (rack-mode).
- This allows to use several rack instances inside a single Carla instance.
- Internal patch-bay mode is also planned, but probably only for 3.0.
-

-
- -


- -
-new-look - -

Internal plugins as LV2

-

- Carla internal plugins are now exported as LV2.
- This includes carla-rack and zynaddsubfx!
- Plugins that released separately (such as DISTRHO and ZamAudio) are not included.
-

-
- -


- -
-new-look - -

Plugin Bridges

-

- Running plugins in a separate process for crash-protection.
- Using a separate process also makes it possible to load plugins with a different architecture from the host,
- such as 32-bit plugins on 64-bit Carla and Windows plugins in Linux.
-
- NOTE: This feature is currently only available within the KXStudio repos.
-

-
- -


- -

More stuff

- -

- There's some other things planned, but they might be delayed until 3.0 so that this release doesn't take too long to happen.
- You can find the complete TODO list here:
- https://raw.github.com/falkTX/Carla/master/doc/Carla-TODO.
-

- -
- -

- > KXStudio repositories now ready for Debian!
- On 2014-04-10 by falkTX -

-

- - The KXStudio repositories are now ready for Debian and its derivatives (including the upcoming Ubuntu 14.04).
- They should work for all Debian versions since Wheezy and Ubuntu 12.04 or above.
- See the Repositories section for more information and how to enable them.
-

-

- There's a list of available applications in the repository here - and plugins here.
- These 2 lists will quickly grow as more stuff is added in the repositories.
-

-


-

- You can request new software to be packaged in this - LinuxMusicians forum topic - (although things seems a bit slow now, we'll eventually get to everyone's requests).
- Please report any issues regarding packages here.
-

-

- If you use the repositories, please donate to help keep packager(s) motivated. See /Donations.
- All this month donations will go to ensure falkTX has a good trip to the Linux Audio Conference next month!
-
-

-

- PS: AVLinux users wanting to use the KXStudio repositories should be patient.
- Something cool might come up when falkTX and GMaq meet in next month's LAC. ;)
-

- -
- -

- > Small Carla notice for JACK1 users (and 1.2.3 release)
- On 2013-12-26 by falkTX -

-

- While I was doing a Carla video I got into a show-stopper bug in JACK2 (it kept crashing because of complex MIDI mixdown, see - this).
- So in the meantime I have to use JACK1, and while doing so I found a pretty nasty bug...
- No system connections were shown in the patchbay canvas!
-

- I don't know if others suffered from the bug (I always run JACK2) or though it was how it really worked.
- In any case, the Carla patchbay will show all JACK connections now - wherever they are from Carla plugins or system ones. -

-

- Updating to version 1.2.3 is recommended, specially if you use JACK1.
- For a list of changes you can check the Carla stable git log - here, - which allows to directly see what changed in the code. -

- -
- -

- > Carla 2.0 development progress report
- On 2013-12-17 by falkTX -

-

- This is a progress report for the new Carla, version 2.0.
- It will take a while to get a release ready, but there are already a few things done and stuff to show. -

-

Backend

-

- First, the backend is being rewritten to not use any system toolkit.
- In 1.x series I've used Qt4 to handle graphics, but that might be a problem soon with Qt5 (cannot mix Qt4 and Qt5 stuff together).
- Plus I want the Carla backend to be toolkit agnostic, so that in the future it may be re-usable for others no matter what their main toolkit is.
- The main backend header files are now ANSI C compatible, thus increasing the chances of re-usability (as some Linux developers have a weird aversion to C++...). -

-

- Because Qt is no longer used in the backend code, I needed something else to handle graphics and other advanced stuff - Juce was selected for this.
- Juce is a C++ framework focused on audio applications and plugins, which suits Carla nicely.
- There's a lot of useful things inside it that will make developing new features much easier (like the internal patchbay mode).
- Other things like AU and VST3 plugin hosting will be possible too thanks to Juce, although they are not relevant to Linux. -

-

- Loading Carla as a plugin is also being worked on.
- There target two main targets with this: -

- -

- If you been following the LinuxMusicians forums you know that internal Carla plugins are already available as LV2 plugins (yes, that includes zynaddsubfx-lv2!).
- Once the Carla internal plugin work is complete, you automatically get an LV2 version of it as well! :D -

-

Front-end

-

- There has been a few changes on the UI side as well.
- For example, the plugin edit dialog now looks like this: -

-

- -

-

- As seen the image, the user will be able to use "Stereo Balance" or "Mono Panning".
- The new layout also allows for a much smaller window size.
-

-

- Lastly, there's plans to bring custom skins to plugin "slots", in a similar way to Reason.
- This is something I still have to investigate to find the best possible way to do it.
- It should be expandable so that random plugins can also use skins, probably via a new LV2 extension.
- More on this later. -

-
-

- That's all for now.
- Soon there will be a new DISTRHO release, so stay tuned! -

- -
- -

- > New releases and future plans
- On 2013-11-27 by falkTX -

-

- Hello everyone, there have been a couple of releases and changes on the KXStudio world.
-

-

- First of, a new release of the KXStudio Live-DVD is now available.
- This is a bug-fix for the 12.04.x series, which current users should already have if their systems are up to date.
- Checkout the About or Release Notes to find out more about this release. -

-

- Several new versions of Carla have been released since its first announcement, the last one currently being 1.2.2.
- For a change-log you can check the git log (stable branch) in github.
- This way you can see what actually changed in the code, instead of just seeing a description list. -

-

- A new DISTRHO release is planned for release next month, and a few minor plugins.
- Hopefully the Plugin Toolkit will be ready by then, which should help the creation of new audio plugins (soon!). -

-

- Lastly, after much discussion and consideration, the KXStudio repositories are moving to Debian.
- The current 12.04.x release is still fully supported, this is something that will happen slowly through 2014.
- Having the KXStudio repos in Debian means any Debian based distribution can make use of KXStudio goods, and not just Ubuntu ones.
- Although there are already happy users with Debian + KXStudio, this process is not yet complete.
- We'll make a new announcement once the Debian repos are ready for wide use. -

-

- Oh, and the KXStudio website is currently being redone a little.
- Give it a visit now! / -

- -
- -

- > Carla Plugin Host 1.0.0 released!
- On 2013-07-02 by falkTX -

-

- After more than 2 years in development, here it is - the first stable release of Carla is now available!
- carla.png
-

-

- Carla Plugin Host, or just Carla, is an audio plugin host, with support for many audio drivers and plugin formats.
- It has some nice features like automation of parameters via MIDI CC and full OSC control.
-

-

- Carla currently supports LADSPA (including LRDF), DSSI, LV2, and VST plugin formats, plus GIG, SF2 and SFZ file support.
- It uses JACK as the default and preferred audio driver but also supports native drivers like ALSA, DirectSound or CoreAudio.
-

-

- We currently release source code plus Windows and Linux binaries (focus goes into the Linux version).
- Downloads available at the usual place, KXStudio Downloads.
-

-

- For more information about Carla check its own application page here.
- We'll be updating that page in the next few days, with some tutorials and workflow videos as well, so stay tuned!
-

-

- You can follow the release discussion over at LinuxMusicians forums.
- If you find this application useful and/or want to help further development, please consider a donation.
-

- - - -
- -

- > KXStudio 12.04.1 released!
- On 2013-01-05 by falkTX -

-

- After much hard work, a new release of KXStudio is ready!
- The previous ISO images were getting old, and since Cadence (and KXStudio in general) is now much more stable, it was time for an update.
- Existing KXStudio users already have 90% of the changes and fixes as KXStudio uses the repositories for everything.
- Still, this is a big milestone for the project. It's a step towards perfection. -

-

- Here's a quick list of changes since the previous 12.04 release. -

-

- - - -

- The DVD works properly now (no need to re-login to apply settings anymore) and also has an option to boot to RAM (requires at least 3Gb to work).
- You can download the new ISOs at the KXStudio website, /Downloads. -

-

-

- This release is dedicated to Hatsuke Miku, a [virtual] Vocaloid singer that recently has seen original artwork released under a Creative Commons license.
- We believe that actions like this one (and others in 2012) indicate that the world embraces open-source culture more and more, every day.
- You can find more about Miku - here, - and the its CC artwork - here. -

-

-

- We hope you enjoy KXStudio and the updated Cadence.
- Soon enough the website will have full documentation for it and other subjects, so stay tuned! -

- -

- Comments and discussion -

- -
- -

- > Call for Testing - Cadence pre-Beta
- On 2012-09-17 by falkTX -

-

- Hello everybody!
- We're almost in the Beta1 release of Cadence!
-
- For those of you who don't know, Cadence is what KXStudio uses to manage the entire audio ecosystem.
- 'Cadence' is by itself the main app of a series of tools (call it the "Cadence tools").
- There's 'Catia', a simple JACK patchbay; 'Claudia' is a ladish frontend, very similar to Catia (and gladish); 'Carla' is the plugin host.
- Then there's the small tools - JackMeter, JackSettings, Logs, Render and XY-Controller (their names give away their funtionality).
-
- Cadence and its tools are currently being documented, and pages will appear here: (incomplete)
- /Applications
- (There's a topic in the KXStudio forums discussing the documentation here).
-
- If you're running KXStudio now, you either have updates or have recently updated Cadence and sub-packages.
- I'll be pushing the latest Cadence code to the KXStudio repositories frequently in the next days while the testing happens.
- ArchLinux users can use this AUR package: - https://aur.archlinux.org/packages.php?ID=50747
- You can checkout what's going on in the Cadence commits page: - https://github.com/falkTX/Cadence/commits/master
-
- Not everything is fully ready right now, here's a list of things that will still be done before the Beta1 release:
- - Cadence audio-bridges, currently disabled
- - Carla Windows plugin-bridge support (Linux 32/64bit bridges are already in place though). Note that this will remain an experimental feature even for this release.
- - Carla-Control is unfinished, the GUI will do nothing useful right now.
- - Catia ALSA-MIDI support is currently disabled, but will still not be activated for this release.
-
-
- So, what needs testing?
- Pretty much everything. :D
- Run the apps, click on random stuff and try to make them crash. When that happens, or if notice something weird, please report the bug.
- I've done my best to make the tools as stable + crash-free as possible, but we can never be too sure about these things.
-
- You can report bugs directly in the official bug page at - https://github.com/falkTX/Cadence/issues.
- (Reporting a bug in that page allows you to receive notifications whenever something is done related to it).
-
-
- Thanks in advance to everyone that decides to help!
- If you love these tools and they are useful to you, please consider making donation by following this link:
- https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PDGZL8PKSNHYW. -

- -
- -

- > KXStudio 12.04 is out!
- On 2011-12-21 by falkTX -

-

- Hey there everyone, it's that time again!
- KXStudio is now ready for the masses, now using Ubuntu 12.04 as the base. -

KDE4 remains the officially supported Desktop, with XFCE on 2nd place.
- For this release I re-introduced the ISOs, although only 32bit for now. So now installing KXStudio can take 3 forms: Live-DVD, Ubuntu upgrade or NetBoot.
- The Live-DVD uses KDE4, if you want XFCE instead please install UbuntuStudio first then follow the upgrade instructions as detailed here. -

The Cadence tools are currently being ported to python3 in a new repo - https://github.com/falkTX/Cadence.
- Catarina, Catia, Claudia and the minor tools are almost beta state right now. Carla and Claudia-Launcher are still in the works (but already very functional), and the real 'Cadence' app is yet to be ported.
- These tools are already available on KXStudio in their latest git state, and will be released as beta for the while world very soon. -

The DISTRHO plugin suite is now near completion and it's targeted for a new release this weekend.
- The entire collection is already available in the KXStudio repos but yet part of the meta-packages (will be added shortly after the official release).
- Generic linux binaries will be made available for non-KXStudio users as before. -

-
- -

- Note: Since the KXStudio website has been internally reworked (removed mediawiki, much simpler PHP code now), the old news have been removed.
-
-

- - diff --git a/News/.gitignore b/News/.gitignore deleted file mode 100644 index 17c6f25..0000000 --- a/News/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -feathers/photo/lib/cache/* -uploads/* -includes/config.yaml.php -includes/database.yaml.php diff --git a/News/.htaccess b/News/.htaccess deleted file mode 100644 index 3daedae..0000000 --- a/News/.htaccess +++ /dev/null @@ -1,7 +0,0 @@ - -RewriteEngine On -RewriteBase /News/ -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^.+$ index.php [L] - diff --git a/News/AUTHORS b/News/AUTHORS deleted file mode 100644 index 00dc043..0000000 --- a/News/AUTHORS +++ /dev/null @@ -1,9 +0,0 @@ -Chyrp is written and maintained by the Chyrp Team: - -Lead Developer: - -- Arian Xhezairi - -Project Founder: - -- Alex Suraci diff --git a/News/COPYING b/News/COPYING deleted file mode 100644 index 77a1b6e..0000000 --- a/News/COPYING +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2011 Chyrp Team (see AUTHORS) and individual contributors. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name(s) of the above -copyright holders shall not be used in advertising or otherwise -to promote the sale, use or other dealings in this Software -without prior written authorization. diff --git a/News/README.markdown b/News/README.markdown deleted file mode 100644 index 10bf69d..0000000 --- a/News/README.markdown +++ /dev/null @@ -1,97 +0,0 @@ -Chyrp is a blogging engine designed to be lightweight while retaining functionality. It is driven by PHP and MySQL (or SQLite), and has a great standard theme and robust module engine. You can personalize and modify it any way you want. - -All of your content is powered by a unique Feathers system that allows Chyrp to be whatever you want it to be. You can post anything and everything, or just stick to the default Text feather and run a regular blog. Chyrp destroys the fine line between a blog and a tumblelog. - -Requirements -============ -Chyrp will thrive on virtually any server setup, but we guarantee Chyrp to run on no less than: - -* PHP 5 >= 5.2.0 -* MySQL: - - MySQL 4.1+ -* SQLite: - - SQLite 3+ - - PDO - -These requirements are more of guidelines, as these are the earliest versions of the services that we have tested Chyrp on. If you are successfully running Chyrp on an earlier version of these services, let us know. - -Installation -============ -Installing Chyrp is easier than you expect. You can do it in four steps: - -1. If using MySQL, create a MySQL database with a username and password. -2. Download, unzip, and upload. -3. Open your web browser and navigate to where you uploaded Chyrp. -4. Follow through the installer at [index.php](). - -That's it! Chyrp will be up and running and ready for you to use. - -Upgrading -========= -Keeping Chyrp up to date is important to make sure that your blog is as safe and as awesome as possible. - -1. Download the latest version of Chyrp from [http://chyrp.net/](http://chyrp.net/). -2. Copy your config files1 to somewhere safe. -3. Disable any Modules/Feathers that you downloaded for the release you're upgrading from. -4. Overwrite your current Chyrp installation files with the new ones. -5. Restore your config files1 back to /includes/. -6. Upgrade by navigating to [upgrade.php](), and restore any backups. -7. Re-enable your Modules/Feathers. -8. Run the upgrader again. It will run the Module/Feather upgrade tasks. - -1 The config files vary depending on what you're upgrading from. Any of these in are considered "config files": - -* `/includes/config.yaml.php` -* `/includes/database.yaml.php` -* `/includes/config.yml.php` -* `/includes/database.yml.php` -* `/includes/config.php` -* `/includes/database.php` - -Extensions -========== -Chyrp isn't complete without activating a few extensions. Extensions add functionality (ex. audio clips, video, photos) to Chyrp. You can find extensions for Chyrp made by the Chyrp community at [http://chyrp.net/extend](http://chyrp.net/extend). - -Installing Extensions -===================== -To install extensions, you have to determine what type of extension it is. It can be a *module*, a *feather*, a *theme*, or a *localization*. There's a different setup process for each type. - -## Feathers -Feathers add new *post types* to Chyrp. Post types determine what kind of media you can display in your blog. - -1. Download and unzip the feather -2. Upload the feather to the `feathers/` folder. -3. Open your web browser and navigate to your Chyrp administration panel. -4. Click on the *Extend* tab, and then the *Feathers* sub tab. -5. Drag it from the Disabled pane to the Enabled pane. - -You can now use the feather by navigating to the Write tab and choosing the feather you uploaded. - -## Modules -Installing modules is quick, easy, and painless with Chyrp. They add extra functionality to Chyrp. - -1. Download and unzip the module. -2. Upload the module to the `modules/` folder. -3. Open your web browser and navigate to your Chyrp administration panel. -4. Click on the *Extend* tab and drag it from the Disabled pane to the Enabled pane. - -The module is now installed and is ready for action. Keep in mind that some modules may conflict with each other if they do similar tasks. They are marked with red lines between them on the Modules page. - -## Themes -Chyrp makes applying themes to your blog easy. With a single click you can change the look of your blog. - -1. Download and unzip the theme. -2. Upload the theme to the `themes/` folder. Make sure that it is contained in it's own folder. -3. Open your web browser and navigate to your Chyrp administration panel. -4. Click on the *Extend* tab, and then the *Themes* sub tab. -5. Click on the screenshot of the theme you just uploaded to apply it to your blog. - -Chyrp can even show you what the theme will look like before anyone else sees it. In the Themes sub tab, click on the Preview button below the theme screenshot to see the theme. - -## Localization -Chyrp is multilingual! If your first language isn't English, you can apply a new localization to Chyrp to make it speak your language. - -1. Download and unzip the localization. -1. Upload the `.mo` file to the `includes/locale/` folder. You don't need anything else for the translation to work. -1. Open your web browser and navigate to your Chyrp administration panel. -1. Click on the *Settings* tab, and change the *Language* option to the language you just uploaded. diff --git a/News/admin/help.php b/News/admin/help.php deleted file mode 100644 index 3aaa673..0000000 --- a/News/admin/help.php +++ /dev/null @@ -1,82 +0,0 @@ - - - - - Chyrp: <?php echo $title; ?> - - - -
-
- -
- - diff --git a/News/admin/index.php b/News/admin/index.php deleted file mode 100644 index cb30857..0000000 --- a/News/admin/index.php +++ /dev/null @@ -1,27 +0,0 @@ -group->can("view_site")) - if ($trigger->exists("can_not_view_site")) - $trigger->call("can_not_view_site"); - else - show_403(__("Access Denied"), __("You are not allowed to view this site.")); - - # Execute the appropriate Controller responder. - $route->init(); - - if (!$route->success and !$admin->displayed) - $admin->display($route->action); # Attempt to display it; it'll go through Modules and Feathers. - - $trigger->call("end", $route); - - ob_end_flush(); diff --git a/News/admin/themes/default/images/icons/add.png b/News/admin/themes/default/images/icons/add.png deleted file mode 100755 index 6332fef..0000000 Binary files a/News/admin/themes/default/images/icons/add.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/appearance.png b/News/admin/themes/default/images/icons/appearance.png deleted file mode 100755 index 73c5b3f..0000000 Binary files a/News/admin/themes/default/images/icons/appearance.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/cancel.png b/News/admin/themes/default/images/icons/cancel.png deleted file mode 100755 index c149c2b..0000000 Binary files a/News/admin/themes/default/images/icons/cancel.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/delete.png b/News/admin/themes/default/images/icons/delete.png deleted file mode 100755 index ebad933..0000000 Binary files a/News/admin/themes/default/images/icons/delete.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/deny.png b/News/admin/themes/default/images/icons/deny.png deleted file mode 100755 index 08f2493..0000000 Binary files a/News/admin/themes/default/images/icons/deny.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/edit.png b/News/admin/themes/default/images/icons/edit.png deleted file mode 100755 index 0bfecd5..0000000 Binary files a/News/admin/themes/default/images/icons/edit.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/error.png b/News/admin/themes/default/images/icons/error.png deleted file mode 100755 index 628cf2d..0000000 Binary files a/News/admin/themes/default/images/icons/error.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/failure.png b/News/admin/themes/default/images/icons/failure.png deleted file mode 100755 index c37bd06..0000000 Binary files a/News/admin/themes/default/images/icons/failure.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/help.png b/News/admin/themes/default/images/icons/help.png deleted file mode 100755 index 5c87017..0000000 Binary files a/News/admin/themes/default/images/icons/help.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/info.png b/News/admin/themes/default/images/icons/info.png deleted file mode 100644 index 9e90193..0000000 Binary files a/News/admin/themes/default/images/icons/info.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/magnifier.png b/News/admin/themes/default/images/icons/magnifier.png deleted file mode 100755 index cf3d97f..0000000 Binary files a/News/admin/themes/default/images/icons/magnifier.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/notice.png b/News/admin/themes/default/images/icons/notice.png deleted file mode 100755 index 12cd1ae..0000000 Binary files a/News/admin/themes/default/images/icons/notice.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/pixel.gif b/News/admin/themes/default/images/icons/pixel.gif deleted file mode 100755 index 35d42e8..0000000 Binary files a/News/admin/themes/default/images/icons/pixel.gif and /dev/null differ diff --git a/News/admin/themes/default/images/icons/save.png b/News/admin/themes/default/images/icons/save.png deleted file mode 100755 index 44c06dd..0000000 Binary files a/News/admin/themes/default/images/icons/save.png and /dev/null differ diff --git a/News/admin/themes/default/images/icons/success.png b/News/admin/themes/default/images/icons/success.png deleted file mode 100755 index 89c8129..0000000 Binary files a/News/admin/themes/default/images/icons/success.png and /dev/null differ diff --git a/News/admin/themes/default/info.yaml b/News/admin/themes/default/info.yaml deleted file mode 100644 index eec468a..0000000 --- a/News/admin/themes/default/info.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Default -version: 2.1 -url: http://chyrp.net/ -description: The default theme provided with Chyrp, which all themes fallback onto. -author: - name: Alex Suraci - url: http://toogeneric.com/ \ No newline at end of file diff --git a/News/admin/themes/default/layout.twig b/News/admin/themes/default/layout.twig deleted file mode 100644 index 403197a..0000000 --- a/News/admin/themes/default/layout.twig +++ /dev/null @@ -1,67 +0,0 @@ - - - - - $site.name: {% block title %}$title{% endblock %} - - - - -${ trigger.call("admin_head") } - - - -
-
- ${ "Log Out ›" | translate } - ${ "Hello, %s!" | translate | format(visitor.full_name | split | first | fallback(visitor.login | fallback("Guest" | translate))) } - ${ "View Site ›" | translate } -
-
- -
-
- {% for notice in flash.notices %} -

$notice

- {% endfor %} - {% for warning in flash.warnings %} -

$warning

- {% endfor %} - {% for message in flash.messages %} -

$message

- {% endfor %} -{% block content %}{% endblock %} -
-
- - - diff --git a/News/admin/themes/default/pages/bookmarklet.twig b/News/admin/themes/default/pages/bookmarklet.twig deleted file mode 100644 index b336dd7..0000000 --- a/News/admin/themes/default/pages/bookmarklet.twig +++ /dev/null @@ -1,287 +0,0 @@ -{% if not done %} - - - - - ${ "Chyrp!" | translate } - - - - - - - {% if site.enabled_feathers | length > 1 %} - -
- {% endif %} -
- {% for feather in feathers %} - - {% endfor %} -
- - -{% else %} {# This one is 100% credited to Tumblr. They did it perfectly, didn't want to muck it up. #} - - - - - ${ "Chyrp!" | translate } - - - - -
-
${ "Done!" | translate }
- - ${ "Close this window" | translate } - - - ${ "or wait 3 seconds." | translate } - -
- - - -{% endif %} diff --git a/News/admin/themes/default/pages/content_settings.twig b/News/admin/themes/default/pages/content_settings.twig deleted file mode 100644 index 01accbc..0000000 --- a/News/admin/themes/default/pages/content_settings.twig +++ /dev/null @@ -1,69 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Content Settings" | translate }{% endblock %} - -{% block content %} -
-
-

- - -

-

- - -

-

- - - - {% if site.clean_urls %} - ${ "Allows you to set an alternative URL for /feed/, e.g. your feed on FeedBurner." | translate } - {% else %} - ${ "Allows you to set an alternative URL for /?feed, e.g. your feed on FeedBurner." | translate } - {% endif %} - -

-

- - - - ${ "The directory, relative to your Chyrp install, to upload files to. You can use /../ to go up one directory." | translate } - -

-

- - - - ${ "Trackbacking allows sites to notify you when they write a new entry, usually because they link to or reference yours." | translate } - -

-

- - - - ${ "Attempts to notify sites linked to from your posts. It'll slow down things a bit when you submit them, depending on how many links you've got in it." | translate } - -

-

- - - - ${ "XML-RPC support allows for remote access to your site. This allows you to use remote clients (e.g., MarsEdit or Flickr) to create/edit content on your site." | translate } - -

-

- - -

- -

- -

- - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/delete_group.twig b/News/admin/themes/default/pages/delete_group.twig deleted file mode 100644 index 93ab940..0000000 --- a/News/admin/themes/default/pages/delete_group.twig +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Delete Group “%s”?" | translate | format(group.name | escape) }{% endblock %} - -{% block content %} -

${ "Are you sure you want to delete the “%s” group?" | translate | format(group.name | escape) }

-
-
-
- {% if group.members %} -

${ "Members:" | translate }

-
    - {% for member in group.members %} -
  • ${ member.full_name | fallback(member.login) }
  • - {% endfor %} -
-
- {% if groups %} -

${ "Move members to:" | translate }

- -
- {% endif %} -
- {% endif %} - {% if group.id == site.default_group and groups %} -

${ "New default group:" | translate }

- -
-
- {% endif %} - {% if group.id == site.guest_group and groups %} -

${ "New “guest” group:" | translate }

- -
-
- {% endif %} -
- -
- - -
- - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/delete_page.twig b/News/admin/themes/default/pages/delete_page.twig deleted file mode 100644 index 6f1d905..0000000 --- a/News/admin/themes/default/pages/delete_page.twig +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Delete Page “%s”?" | translate | format(page.title | escape) }{% endblock %} - -{% block content %} -

${ "Are you sure you want to delete “%s”?" | translate | format(page.title) }

-
-
-
-

${ "Excerpt" | translate }

- ${ page.body | truncate(500) } - {% if page.children %} -
-

${ "Delete children?" | translate }

-
    - {% for child in page.children %} -
  • $child.title
  • - {% endfor %} -
- {% endif %} -
-
- -
- - -
- - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/delete_post.twig b/News/admin/themes/default/pages/delete_post.twig deleted file mode 100644 index fc8acbc..0000000 --- a/News/admin/themes/default/pages/delete_post.twig +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Delete “%s”?" | translate | format(post.title | escape) }{% endblock %} - -{% block content %} -

${ "Are you sure you want to delete “%s”?" | translate | format(post.title) }

-
-
-
-

${ "Excerpt" | translate }

- $post.excerpt -
-
- -
- - -
- - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/delete_user.twig b/News/admin/themes/default/pages/delete_user.twig deleted file mode 100644 index c56da15..0000000 --- a/News/admin/themes/default/pages/delete_user.twig +++ /dev/null @@ -1,89 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Delete User “%s”?" | translate | format(user.login | escape) }{% endblock %} - -{% block content %} -

${ "Are you sure you want to delete user “%s”?" | translate | format(user.login | escape) }

-
-
-
-

${ "Information" | translate }

-
    - {% if user.full_name %} -
  • ${ "Full Name:" | translate } $user.full_name
  • - {% endif %} -
  • ${ "E-Mail:" | translate } $user.email
  • - {% if user.website %} -
  • ${ "Website:" | translate } $user.website
  • - {% endif %} -
  • ${ "Group:" | translate } $user.group.name
  • -
-
- {% if user.posts %} -

${ "Posts:" | translate }

-
    - {% for post in user.posts %} -
  • $post.title
  • - {% endfor %} -
-
- {% if users %} -

- - ${ "Attribute posts to:" | translate } -

- -
- {% endif %} -

- - ${ "Delete posts." | translate } -

-
-
- {% endif %} - {% if user.pages %} -

${ "Pages:" | translate }

-
    - {% for page in user.pages %} -
  • $page.title
  • - {% endfor %} -
-
- {% if users %} -

- - ${ "Attribute pages to:" | translate } -

- -
- {% endif %} -

- - ${ "Delete pages." | translate } -

-
-
- {% endif %} -${ trigger.call("delete_user_form") } -
-
- -
- - -
- - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/edit_group.twig b/News/admin/themes/default/pages/edit_group.twig deleted file mode 100644 index d3a6e1b..0000000 --- a/News/admin/themes/default/pages/edit_group.twig +++ /dev/null @@ -1,36 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Edit Group “%s”" | translate | format(group.name | escape) }{% endblock %} - -{% block content %} - ${ group.delete_link('delete'~ ("Delete" | translate), null, null, "button boo right") } -

${ "Editing Group “%s”" | translate | format(group.name | escape) }

-
-
-

- - -

- -

${ "Permissions" | translate }

-

- -

-
- {% for permission in permissions %} -

- - -

- {% endfor %} -
- -

- -

- - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/edit_page.twig b/News/admin/themes/default/pages/edit_page.twig deleted file mode 100644 index 7432b71..0000000 --- a/News/admin/themes/default/pages/edit_page.twig +++ /dev/null @@ -1,16 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Edit “%s”" | translate | format(page.title | escape) }{% endblock %} - -{% block content %} - ${ page.delete_link('delete'~ ("Delete" | translate), null, null, "button boo right") } -

${ "Editing “%s”" | translate | format(page.title) }

-
-
-{% include "partials/page_fields.twig" %} - - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/edit_post.twig b/News/admin/themes/default/pages/edit_post.twig deleted file mode 100644 index a889323..0000000 --- a/News/admin/themes/default/pages/edit_post.twig +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Edit “%s”" | translate | format(post.title | escape) }{% endblock %} - -{% block content %} - ${ post.delete_link('delete'~ ("Delete" | translate), null, null, "button boo right") } -

${ "Editing “%s”" | translate | format(post.title | escape) }

-
-
-{% include "partials/post_fields.twig" %} - - - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/edit_user.twig b/News/admin/themes/default/pages/edit_user.twig deleted file mode 100644 index 9bab373..0000000 --- a/News/admin/themes/default/pages/edit_user.twig +++ /dev/null @@ -1,57 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Edit User “%s”" | translate | format(user.login | escape) }{% endblock %} - -{% block content %} - ${ user.delete_link('delete'~ ("Delete" | translate), null, null, "button boo right") } -

${ "Editing User “%s”" | translate | format(user.login | escape) }

-
-
-

${ "Information" | translate }

-

- - -

-

- - -

-

- - -

- -

${ "Settings" | translate }

-

- - -

-

- - -

-

- - -

-

- - -

- ${ trigger.call("edit_user_fields", user) } - -
- -

- -

- - - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/export.twig b/News/admin/themes/default/pages/export.twig deleted file mode 100644 index 678d349..0000000 --- a/News/admin/themes/default/pages/export.twig +++ /dev/null @@ -1,62 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Export" | translate }{% endblock %} - -{% block content %} -

${ "What would you like to export?" | translate }

-
-
-

- - - - ${ "filter:" | translate } - - help - ${ "(optional)" | translate } - -

-

- - - - ${ "filter:" | translate } - - help - ${ "(optional)" | translate } - -

-

- - - - ${ "filter:" | translate } - - help - ${ "(optional)" | translate } - -

-

- - - - ${ "(warning: this also exports the hashed passwords, keep it safe)" | translate } - - - ${ "filter:" | translate } - - help - ${ "(optional)" | translate } - -

- - ${ trigger.call("export_choose") } - -

- -

- - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/feathers.twig b/News/admin/themes/default/pages/feathers.twig deleted file mode 100644 index 52a8250..0000000 --- a/News/admin/themes/default/pages/feathers.twig +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Feathers" | translate }{% endblock %} - -{% block content %} -
-

${ "Enabled" | translate }

-
    - {% for safename, feather in enabled_feathers | items %} -
  • - - {% if feather.help %} - help - {% endif %} - ${ "%s v%s by %s" | translate | format(feather.url, feather.name | translate(safename), feather.version, feather.author.link) } -
    -
    - $feather.description {# translation is done in the controller #} -
    - -
    -
  • - {% endfor %} -
-
-
-

${ "Disabled" | translate }

-
    - {% for safename, feather in disabled_feathers | items %} -
  • - - {% if feather.help %} - help - {% endif %} - ${ "%s v%s by %s" | translate | format(feather.url, feather.name | translate(safename), feather.version, feather.author.link) } -
    -
    - $feather.description {# translation is done in the controller #} -
    - -
    -
  • - {% endfor %} -
-
-
-
- ${ "Get More Feathers ›" | translate } -{% endblock %} diff --git a/News/admin/themes/default/pages/general_settings.twig b/News/admin/themes/default/pages/general_settings.twig deleted file mode 100644 index 1b76668..0000000 --- a/News/admin/themes/default/pages/general_settings.twig +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Site Configuration" | translate }{% endblock %} - -{% block content %} -
-
-

- - -

-

- - -

-

- - -

-

- - - help - - ${ "Enter an alternate address here if you want your homepage URL to be different from the URL where Chyrp is normally available." | translate } - -

-

- - -

-

- - -

-

- - -

- -

- -

- - -
-
-{% endblock %} diff --git a/News/admin/themes/default/pages/import.twig b/News/admin/themes/default/pages/import.twig deleted file mode 100644 index 4345129..0000000 --- a/News/admin/themes/default/pages/import.twig +++ /dev/null @@ -1,176 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Import" | translate }{% endblock %} - -{% block content %} -

Chyrp

-
-
-

- - -

-

- - -

-

- - -

-

- - -

-

- - - - ${ "Usually something like http://example.com/uploads/." | translate } - -

- - ${ trigger.call("import_choose") } - -

- -

- - -
-
-
-
-
-

WordPress

-
-
-

- - -

-

- - - - ${ "Usually something like http://example.com/wp-content/uploads/." | translate } - -

- -

- -

- - -
-
-
-
-
-

Tumblr

-
-
-

- - - ${ "Note: Audio tumbles cannot be imported." | translate } -

- -

- -

- - -
-
-
-
-
-

TextPattern

-
-
-

- - -

-

- - -

-

- - -

-

- - -

-

- - - ${ "(if any)" | translate } -

-

- - - - ${ "Usually something like http://example.com/images/." | translate } - -

-

- -

- - -
-
-
-
-
-

MovableType

-
-
-

- - -

-

- - -

-

- - -

-

- - -

-

- - - - ${ "Usually something like http://example.com/images/." | translate } - -

-

- -

- - -
-
- ${ trigger.call("import_choose") } -{% endblock %} diff --git a/News/admin/themes/default/pages/manage_groups.twig b/News/admin/themes/default/pages/manage_groups.twig deleted file mode 100644 index 65f18d1..0000000 --- a/News/admin/themes/default/pages/manage_groups.twig +++ /dev/null @@ -1,47 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Manage Groups" | translate }{% endblock %} - -{% block content %} -

${ "Need more detail?" | translate }

-
-
- - {% if visitor.group.can("add_group") %} - - add ${ "New Group" | translate } - - {% endif %} -
-

${ "Search all groups for user…" | translate }

- -
-
-
-
-

${ "Groups" | translate }

- {% for group in groups.paginated %} -
-

- - ${ group.edit_link('edit '~("edit" | translate)) } - ${ group.delete_link('delete '~("delete" | translate)) } - - {% if group.id == site.guest_group %} - ${ "“%s” is the group for guests." | translate | format(group.name) } - {% elseif group.id == site.default_group %} - ${ "“%s” is the default group and has %d member." | translate_plural("“%s” is the default group and has %d members.", group.size) | format(group.name, group.size, route.url("/admin/?action=manage_users&query=group%3A"~group.name)) } - {% else %} - ${ "“%s” has %d member." | translate_plural("“%s” has %d members.", group.size) | format(group.name, group.size, route.url("/admin/?action=manage_users&query=group%3A"~group.name)) } - {% endif %} -

-
- {% endfor %} - {% if groups.paginated and groups.pages > 1 %} - - {% endif %} -{% endblock %} diff --git a/News/admin/themes/default/pages/manage_pages.twig b/News/admin/themes/default/pages/manage_pages.twig deleted file mode 100644 index 2f5a7cd..0000000 --- a/News/admin/themes/default/pages/manage_pages.twig +++ /dev/null @@ -1,91 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Manage Pages" | translate }{% endblock %} - -{% block content %} -

${ "Need more detail?" | translate }

-
-
- -
-

- ${ "Search…" | translate } - help -

- -
-
-
-
-

{% if GET.query %}${ "Search Results" | translate }{% else %}${ "Last 25 Pages" | translate }{% endif %}

- - - - - - - - ${ trigger.call("manage_pages_column_header") } - - - - - {% for page in pages.paginated %} - - - - - - ${ trigger.call("manage_pages_column", page) } - {% if page.editable and page.deletable %} - - - {% else %} - ${ page.edit_link('edit '~("edit" | translate), '') } - ${ page.delete_link('delete '~("delete" | translate), '') } - {% endif %} - - {% else %} - - - - {% endfor %} - -
${ "Title" | translate }${ "Created" | translate }${ "Last Updated" | translate }${ "Author" | translate }${ "Controls" | translate }
${ page.title | truncate }${ page.created_at | strftime }{% if page.updated %}${ page.updated_at | strftime }{% else %}${ "never" | translate }{% endif %}$page.user.login${ page.edit_link('edit '~("edit" | translate)) }${ page.delete_link('delete '~("delete" | translate)) }', '', '
${ "(none)" | translate }
- {% if pages.paginated and pages.pages > 1 %} -
- - {% endif %} - {% if pages.total %} -
-

${ "Reorder Pages" | translate }

-
-
    - {% for item in theme.pages_list %} -
  • - -
    $item.page.title
    - - {% if item.has_children %}
      {% endif %} - {% if not item.has_children %}{% endif %} - - {% for ul, li in item.end_tags %} - $ul - $li - {% endfor %} - {% endfor %} -
    - -
  • - {% endif %} -{% endblock %} diff --git a/News/admin/themes/default/pages/manage_posts.twig b/News/admin/themes/default/pages/manage_posts.twig deleted file mode 100644 index c65269c..0000000 --- a/News/admin/themes/default/pages/manage_posts.twig +++ /dev/null @@ -1,74 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Manage Posts" | translate }{% endblock %} - -{% block content %} -

    ${ "Need more detail?" | translate }

    -
    -
    - -
    -

    - ${ "Search…" | translate } - help -

    - -
    -
    -

    ${ "Browse by month:" | translate }

    - - -
    -
    -
    -
    -
    -

    {% if GET.query %}${ "Search Results" | translate }{% else %}${ "Last 25 Posts" | translate }{% endif %}

    - - - - - - - - ${ trigger.call("manage_posts_column_header") } - - - - - {% for post in posts.paginated %} - - - - - - ${ trigger.call("manage_posts_column", post) } - {% if post.editable and post.deletable %} - - - {% elseif post.editable or post.deletable %} - ${ post.edit_link('edit '~("edit" | translate), '') } - ${ post.delete_link('delete '~("delete" | translate), '') } - {% endif %} - - {% else %} - - - - {% endfor %} - -
    ${ "Title" | translate }${ "Posted" | translate }${ "Status" | translate }${ "Author" | translate }${ "Controls" | translate }
    ${ post.title | truncate }${ post.created_at | strftime }$post.status_name$post.user.login${ post.edit_link('edit '~("edit" | translate)) }${ post.delete_link('delete '~("delete" | translate)) }', '', '
    ${ "(none)" | translate }
    - {% if posts.paginated and posts.pages > 1 %} -
    - - {% endif %} -{% endblock %} diff --git a/News/admin/themes/default/pages/manage_users.twig b/News/admin/themes/default/pages/manage_users.twig deleted file mode 100644 index e63e2a9..0000000 --- a/News/admin/themes/default/pages/manage_users.twig +++ /dev/null @@ -1,74 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Manage Users" | translate }{% endblock %} - -{% block content %} -

    ${ "Need more detail?" | translate }

    -
    -
    - - {% if visitor.group.can("add_user") %} - - add ${ "New User" | translate } - - {% endif %} -
    -

    - ${ "Search…" | translate } - help -

    - -
    -
    -
    -
    -

    ${ "Users" | translate }

    - - - - - - - - ${ trigger.call("manage_users_column_header") } - - - - - {% for user in users.paginated %} - - - - - - ${ trigger.call("manage_users_column", user) } - {% if user.editable and user.deletable %} - - - {% else %} - ${ user.edit_link('edit '~("edit" | translate), '') } - ${ user.delete_link('delete '~("delete" | translate), '') } - {% endif %} - - {% else %} - - - - {% endfor %} - -
    ${ "Name" | translate }${ "Group" | translate }${ "Joined" | translate }${ "Website" | translate }${ "Controls" | translate }
    - {% if user.full_name != "" %} - $user.full_name ($user.login) - {% else %} - $user.login - {% endif %} - ${ user.group.name | escape }${ user.joined_at | strftime }{% if user.website != "" %}$user.website{% endif %}${ user.edit_link('edit '~("edit" | translate)) }${ user.delete_link('delete '~("delete" | translate)) }', '', '
    ${ "(none)" | translate }
    - {% if users.paginated and users.pages > 1 %} -
    - - {% endif %} -{% endblock %} diff --git a/News/admin/themes/default/pages/modules.twig b/News/admin/themes/default/pages/modules.twig deleted file mode 100644 index ab087de..0000000 --- a/News/admin/themes/default/pages/modules.twig +++ /dev/null @@ -1,71 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Modules" | translate }{% endblock %} - -{% block content %} -
    -

    ${ "Enabled" | translate }

    -
      - {% for safename, module in enabled_modules | items %} -
    • - - {% if module.help %} - help - {% endif %} - ${ "%s v%s by %s" | translate | format(module.url, module.name | translate(safename), module.version, module.author.link) } -
      -
      - $module.description {# translation is done in the controller #} - - - -
      - {% if not module.dependencies_needed %} - - {% endif %} -
      -
    • - {% endfor %} -
    -
    -
    -

    ${ "Disabled" | translate }

    -
      - {% for safename, module in disabled_modules | items %} -
    • - - {% if module.help %} - help - {% endif %} - ${ "%s v%s by %s" | translate | format(module.url, module.name | translate(safename), module.version, module.author.link) } -
      -
      - $module.description {# translation is done in the controller #} - - - -
      - {% if not module.dependencies_needed %} - - {% endif %} -
      -
    • - {% endfor %} -
    -
    -
    -
    - ${ "Get More Modules ›" | translate } -{% endblock %} diff --git a/News/admin/themes/default/pages/new_group.twig b/News/admin/themes/default/pages/new_group.twig deleted file mode 100644 index ba1916b..0000000 --- a/News/admin/themes/default/pages/new_group.twig +++ /dev/null @@ -1,34 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "New Group" | translate }{% endblock %} - -{% block content %} -

    ${ "New Group" | translare }

    -
    -
    -

    - - -

    - -

    ${ "Permissions" | translate }

    -

    - -

    -
    - {% for permission in permissions %} -

    - - -

    - {% endfor %} -
    - -

    - -

    - - -
    -
    -{% endblock %} diff --git a/News/admin/themes/default/pages/new_user.twig b/News/admin/themes/default/pages/new_user.twig deleted file mode 100644 index 0f7052d..0000000 --- a/News/admin/themes/default/pages/new_user.twig +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Add User" | translate }{% endblock %} - -{% block content %} -

    ${ "New User" | translare }

    -
    -
    -

    ${ "Settings" | translate }

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - -

    ${ "Information" | translate }

    -

    - - -

    -

    - - -

    -

    - - -

    - - - ${ trigger.call("new_user_fields") } - -
    - -

    - -

    - - -
    -
    -{% endblock %} diff --git a/News/admin/themes/default/pages/route_settings.twig b/News/admin/themes/default/pages/route_settings.twig deleted file mode 100644 index 12f64bc..0000000 --- a/News/admin/themes/default/pages/route_settings.twig +++ /dev/null @@ -1,50 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Route Settings" | translate }{% endblock %} - -{% block content %} -
    -
    -

    - - - ${ "(recommended)" | translate } - - ${ "Gives your site prettier urls." | translate }
    - ${ "Requires .htaccess support (pretty common). If you're unsure, it's safe to test and find out. Just come back and disable it if it breaks your site." | translate } -
    -

    -

    - - -

    -
    - ${ "Syntax:" | translate } -
      -
    • (year): ${ "Year submitted" | translate } ${ "(ex. 2007)" | translate }
    • -
    • (month): ${ "Month submitted" | translate } ${ "(ex. 12)" | translate }
    • -
    • (day): ${ "Day submitted" | translate } ${ "(ex. 25)" | translate }
    • -
    • (hour): ${ "Hour submitted" | translate } ${ "(ex. 03)" | translate }
    • -
    • (minute): ${ "Minute submitted" | translate } ${ "(ex. 59)" | translate }
    • -
    • (second): ${ "Second submitted" | translate } ${ "(ex. 30)" | translate }
    • -
    • (id): ${ "Post ID" | translate }
    • -
    • (author): ${ "Post author (username)" | translate } ${ "(ex. Alex)" | translate }
    • -
    • (clean): ${ "The non-unique sanitized name" | translate } ${ "(ex. this_is_clean)" | translate }
    • -
    • (url): ${ "The unique form of (clean)" | translate } ${ "(ex. this_one_is_taken_2)" | translate }
    • -
    • (feather): ${ "The post's feather" | translate } ${ "(ex. text)" | translate }
    • -
    • (feathers): ${ "The plural form of the post's feather" | translate } ${ "(ex. links)" | translate }
    • - ${ trigger.call("post_view_url_settings") } -
    -
    - -

    - -

    - - -
    -
    -{% endblock %} diff --git a/News/admin/themes/default/pages/themes.twig b/News/admin/themes/default/pages/themes.twig deleted file mode 100644 index 4a2006b..0000000 --- a/News/admin/themes/default/pages/themes.twig +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Themes" | translate }{% endblock %} - -{% block content %} - {% for theme in themes %} -
    - - ${ theme.info.name | translate(theme.name) | escape } - {% if theme.screenshot %} - ${ (' - {% endif %} - - {% if theme.screenshot %} -
    - {% endif %} - ${ "v%s by %s" | translate | format(theme.info.version, theme.info.author.link) } -
    -
    - {% if theme.name == site.theme %} - current theme${ "Current Theme" | translate } - {% else %} - Select${ "Select" | translate } - Preview${ "Preview" | translate } - {% endif %} -
    - {% endfor %} -
    -
    -

    ${ "Admin Themes" | translate }

    - {% for theme in admin_themes %} -
    - - ${ theme.info.name | translate(theme.name) | escape } - {% if theme.screenshot %} - ${ (' - {% endif %} - - {% if theme.screenshot %} -
    - {% endif %} - ${ "v%s by %s" | translate | format(theme.info.version, theme.info.author.link) } -
    -
    - {% if theme.name == admin_theme %} - current theme${ "Current Theme" | translate } - {% else %} - Select${ "Select" | translate } - {% endif %} -
    - {% endfor %} -
    -
    - ${ "Get More Themes ›" | translate } -{% endblock %} diff --git a/News/admin/themes/default/pages/user_settings.twig b/News/admin/themes/default/pages/user_settings.twig deleted file mode 100644 index adf7bd3..0000000 --- a/News/admin/themes/default/pages/user_settings.twig +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "User Settings" | translate }{% endblock %} - -{% block content %} -
    -
    -

    - - - ${ "Allow people to register" | translate } -

    -

    - - -

    -

    - - -

    - -

    - -

    - - -
    -
    -{% endblock %} diff --git a/News/admin/themes/default/pages/write_page.twig b/News/admin/themes/default/pages/write_page.twig deleted file mode 100644 index 63658c3..0000000 --- a/News/admin/themes/default/pages/write_page.twig +++ /dev/null @@ -1,13 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Add Page" | translate }{% endblock %} - -{% block content %} -
    -
    -{% include "partials/page_fields.twig" %} - - -
    -
    -{% endblock %} diff --git a/News/admin/themes/default/pages/write_post.twig b/News/admin/themes/default/pages/write_post.twig deleted file mode 100644 index c6e8ef7..0000000 --- a/News/admin/themes/default/pages/write_post.twig +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "layout.twig" %} - -{% block title %}${ "Write" | translate }{% endblock %} - -{% block content %} -
    -
    -{% include "partials/post_fields.twig" %} - - - -
    -
    -{% endblock %} diff --git a/News/admin/themes/default/partials/page_fields.twig b/News/admin/themes/default/partials/page_fields.twig deleted file mode 100644 index bd2faa1..0000000 --- a/News/admin/themes/default/partials/page_fields.twig +++ /dev/null @@ -1,49 +0,0 @@ - ${ trigger.call("before_page_fields") } -

    - - -

    -

    - - -

    - ${ trigger.call("after_page_fields") } - -
    - -
    - -
    - -
    -

    - -   -

    -

    - - -

    -

    - - -

    - {% if route.action == "write_page" %} - ${ trigger.call("new_page_options") } - {% else %} - ${ trigger.call("edit_page_options", page) } - {% endif %} -
    -
    - diff --git a/News/admin/themes/default/partials/post_fields.twig b/News/admin/themes/default/partials/post_fields.twig deleted file mode 100644 index cce32b2..0000000 --- a/News/admin/themes/default/partials/post_fields.twig +++ /dev/null @@ -1,133 +0,0 @@ - ${ trigger.call("before_post_fields", feather) } - {% for field in feather.fields %} -

    - - {% if field.type == "text" or field.type == "file" %} - - {% if post.filename and route.action == "edit_post" %} - Current file name: ${ post.filename | escape('') } - {% endif %} - {% elseif field.type == "text_block" %} - - {% elseif field.type == "checkbox" %} - - {% elseif field.type == "select" %} - - {% endif %} - $field.extra -

    - {% endfor %} - ${ trigger.call("after_post_fields", feather) } - -
    - {% if route.action == "edit_post" %} - - {% else %} - {% if visitor.group.can("add_post") %} - - {% endif %} - - {% endif %} -
    - -
    - -
    - {% if visitor.group.can("add_post") %} -

    - - -

    - {% endif %} -

    - -   - ${ "(shows this post above all others)" | translate } -

    -

    - - -

    -

    - - - -

    -

    - - - -

    - {% for field in options %} -

    - - {% if field.type == "text" or field.type == "file" %} - - {% elseif field.type == "text_block" %} - - {% elseif field.type == "select" %} - - {% endif %} - $field.extra -

    - {% endfor %} -
    -
    - \ No newline at end of file diff --git a/News/admin/themes/default/style.css b/News/admin/themes/default/style.css deleted file mode 100644 index 870289a..0000000 --- a/News/admin/themes/default/style.css +++ /dev/null @@ -1,948 +0,0 @@ -/* @group Reset */ -body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td { margin: 0; padding: 0; } -table { border-collapse: collapse; border-spacing: 0; } -fieldset,img { border: 0; } -address,caption,cite,code,dfn,em,strong,th,var { font-style: normal; font-weight: normal; } -li { list-style: none; } -caption,th { text-align: left; } -h1,h2,h3,h4,h5,h6 { font-size: 100%; font-weight: normal; } -abbr,acronym { border: 0; font-variant: normal; } -input,textarea,select { font-family: inherit; font-size: inherit; font-weight: inherit; } -a:link, a:visited { text-decoration: none; color: inherit; } -/* @end */ - -/* @group Core */ -html { - font-size: 62.5%; -} -body { - font: 1.25em/1.5em normal Lucida Grande, Helvetica, Arial, sans-serif; - color: #333; - background: #efefef; -} - -h1, h2, h3, h4, h5, h6{ - font-weight: normal !important; - font-family: "Palatino Linotype", Chaparral Pro, Georgia, serif; -} - -em { - font-style: italic; -} -strong { - font-weight: bold; -} -small, -.small { - font-size: .9em; - color: #999; -} -p { - margin: 0 0 1em; -} -a:link, -a:visited { - text-decoration: underline; -} -/* @end */ - -/* @group Header */ -#header { - background: #353535; - padding: 2em 0; - color: #fff; - position: relative; -} -#header h1 { - font-size: 2em; - line-height: 1.25em; - text-shadow: #000 0 1px 1px; -} -#header h1 a { - text-decoration: none; -} -#header #navigation { - float: right; - position: absolute; - bottom: 0; - right: 5em; -} -#header #navigation li { - display: inline; -} -#header #navigation li a:link, -#header #navigation li a:visited { - float: left; - margin-left: 1em; - text-shadow: #000 0 0 0; - background: #444; - color: #ebeeee; - height: 4em; - line-height: 4em; - text-transform: uppercase; - width: 8em; - text-align: center; - text-decoration: none; - font-family: "Palatino Linotype", Chaparral Pro, Georgia, serif; - letter-spacing: 0.2em; - font-size: 0.8em; -} -#header #navigation li.selected a:link, -#header #navigation li.selected a:visited { - background: #fff; - color: #333; -} - -#header #navigation li a:hover { - background: #4c4c4c; -} - -#welcome { - background: #fff; - padding: .9em 0; - border-bottom: 1px solid #e1e1e1; -} -#welcome a:link, -#welcome a:visited { - text-decoration: none; - background: #fcfcfc; - padding: 1em; - margin: -1em 0 -.8em; -} -#welcome .right { - padding: .9em 1em !important; - margin-top: -.9em !important; -} -#welcome a:hover { - background: #f5f5f5; -} -#welcome a:active { - background: #f0f0f0; -} -/* @end */ - -/* @group Footer */ -#footer { - width: 425px; - margin: 2.5em auto !important; - font-size: 1.25em; - text-align: center; -} -#footer .sub { - color: #acacac; - font-size: .7em; -} -/* @end */ - -/* @group Sub-Navigation */ -#sub-nav { - margin-top: 2em; -} -#sub-nav li { - float: left; - position: relative; - top: 1px; - z-index: 1; -} -#sub-nav li a:link, -#sub-nav li a:visited { - float: left; - padding: .4em .75em; - background: #dfdfdf; - border-bottom: 0; - color: #737373; - text-decoration: none; - margin: 0 0.7em 0 0; -} -#sub-nav li a:hover { - background: #e5e5e5; -} -#sub-nav li.selected a:link, -#sub-nav li.selected a:visited { - background: #fff; - border: 1px solid #e1e1e1; - border-bottom: none; -} -#sub-nav li.right { - margin: .75em 0 0; -} -#sub-nav li.right a:link, -#sub-nav li.right a:visited { - float: none; - background: transparent; - padding: 0; - font-size: .95em; - color: #444; -} -.feathers_sort { - background: #eee; - margin-top: .2em; - height: 2.3em !important; - border-left: .1em dashed #ccc; - border-right: .1em dashed #ccc; -} -/* @end */ - -/* @group Content */ -#content { - background: #fff; - padding: 1em; - border: 1px solid #e1e1e1; - position: relative; -} -#content > form { - /* margin-top: .5em; */ -} -#content h1 { - font-size: 2em; - margin: .2em 0 1em; - color: #aaa; - font-weight: bold; -} -#content h2 { - font-size: 1.5em; - margin: 0 0 .5em; - color: #666; - font-weight: normal; -} -#content h3 { - font-weight: bold; - font-size: 1.25em; - margin-bottom: 1.5em; -} -#content h4 { - font-weight: bold; - font-size: 1.2em; -} -/* @end */ - -/* @group Extend */ -.enable, -.disable { - width: 49%; -} -.enable h2, -.disable h2 { - font-weight: normal !important; - font-size: 1.1em !important; -} -.enable h2 .sub, -.disable h2 .sub { - font-size: .8em; - color: #bcbcbc; -} -.enable ul, -.disable ul { - padding: 1em 1em .5em; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; -} -.enable ul li, -.disable ul li { - padding: .1em .25em .1em .7em; - margin: 0 0 .5em; - list-style: disc inside !important; - position: relative; -} -.enable ul li img, -.disable ul li img { - position: absolute; - top: 4px; - right: 4px; -} -.enable ul li a.help img, -.disable ul li a.help img { - top: 3px; - right: 20px; - width: 15px; - height: 15px; -} -.enable ul li .sub, -.disable ul li .sub { - font-size: .9em; -} -.enable ul li .enable_button, -.disable ul li .disable_button { - display: block; - padding: .25em .5em; - text-align: right; -} -ul.extend .expand { - margin: 0 -.25em 0 -.7em; -} -.enable h2 { - color: #4f8f62 !important; -} -.enable ul { - background: #dbffe6; - border: 1px solid #dbffe6; -} -.enable ul li { - background: #e6ffee; - color: #386345; -} -.enable ul.hover { - border: 1px solid #b3d1bb; -} -.enable ul li a:link, -.enable ul li a:visited, -.enable ul li .sub a:hover { - text-decoration: none; - color: #386345; -} -.enable ul li .sub, -.enable ul li .sub a:link, -.enable ul li .sub a:visited { - color: #74a683; -} -.enable ul li .description { - padding: .5em; - background: #F7FFF9; -} -.enable ul li .enable_button { - color: #189100; -} -.enable ul li .enable_button:hover { - background: #189100; - color: #fff; -} -.enable ul li .enable_button:active { - background: #067000; -} -.disable h2 { - color: #ff7070 !important; -} -.disable ul { - background: #ffdbdb; - border: 1px solid #ffdbdb; -} -.disable h2 .sub { - color: #bcbcbc; -} -.disable ul li { - background: #ffe6e6; - color: #653b3d; -} -.disable ul.hover { - border: 1px solid #cfb2b2; -} -.disable ul li a:link, -.disable ul li a:visited, -.disable ul li .sub a:hover { - text-decoration: none; - color: #7b4d4d; -} -.disable ul li .sub, -.disable ul li .sub a:link, -.disable ul li .sub a:visited { - color: #a97f7f; -} -.disable ul li .description { - padding: .5em; - background: #FFF1F1; -} -.disable ul li .disable_button { - color: #d51800; -} -.disable ul li .disable_button:hover { - background: #d51800; - color: #fff; -} -.disable ul li .disable_button:active { - background: #b30600; -} -/* @end */ - -/* @group Theme Changing */ -.theme { - text-align: center; - margin-right: 15px !important; - border: 0 !important; - padding-bottom: 20px !important; - position: relative; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; -} -.theme.last { - margin-right: 0 !important; -} -.theme .link { - font-weight: bold; - text-align: center; - text-decoration: none; -} -.theme .link span { - display: block; -} -.theme.current { - background: #EBFAE4; - color: #65845e; -} -.theme.current small, -.theme.current small a:link, -.theme.current small a:visited { - color: #789f72; -} -.theme.current .button { - background: #189100; - color: #FFF; - border: 0; -} -.theme img.screenshot { - padding: 5px; - background: #FFF; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; -} -.theme a:hover img.screenshot { - background: #CCC; -} -.theme small { - font-weight: normal; -} -/* @end */ - -/* @group Forms */ -form.delete blockquote { - width: 75%; - margin: 0 auto; - font-style: italic; -} -form.delete blockquote h2, -form.delete .noitalic { - font-style: normal; -} -form.delete blockquote h2 input[type="checkbox"] { - position: relative; - top: -.125em; -} -form.delete h2.inline { - display: inline; -} -form.delete select { - position: relative; - top: -2px; -} -form.split label { - width: 41%; - float: left; - text-align: right; - font-weight: bold; - padding: 4px 2% 5px; - color: #999; -} -form.split label .sub { - display: block; -} -form.split label input { - margin: -.5em 0; -} -form.split select { - margin: 3px 0 .5em; -} -form.split small, -form.split .small { - display: block; - margin-left: 45%; -} -form.split button { - margin-left: 45%; -} -form .buttons { - margin-top: 2em; -} -label { - display: block; - font-size: 1.1em; -} -form p .sub, -label .sub, -tr .sub { - font-size: .8em; - color: #999; - font-weight: normal; -} -input.text, -input[type="text"], -input[type="password"], -input.file, -textarea { - font-size: 1.25em; - padding: 3px; - border: 1px solid #ddd; - background: #fff; -} -input.file { - border: none; -} -input.text, -input.file, -select, -textarea { - margin-bottom: .25em; -} -input.text { - /* width: 15em; */ -} -input.checkbox { - margin: .6em .5em .75em 0; -} -span.checkbox { - position: relative; - top: -3px; -} -textarea { - font-size: 1.1em; - font-family: "Monaco", "Consolas", monospace; -} -textarea.wide, -input.text.wide { - padding: .5%; - width: 99%; - _width: 100%; /* Hooray for IE6's randomized box model. */ -} -input.code, -textarea.code, -code { - font-family: "Consolas", "Monaco", monospace; -} -/* @end */ - -/* @group Tables */ -table thead tr { - background: #555; - color: #fff; - border: 0 !important; - border-bottom: 2px solid #444; - text-shadow: #333 0px 1px 0px; -} -table thead tr th { - padding: .25em .5em; - font-weight: bold; -} -table thead tr th input { - vertical-align: middle; - margin: -5px 0 0 !important; -} -table thead tr th.header { - cursor: pointer; -} -table thead tr th.headerSortDown, -table thead tr th.headerSortUp { - background: #444; -} -table tbody tr { - -} -table tbody tr.last { - -} -table tbody tr td { - padding: .5em .7em; - border-right: 1px solid #eee; - border-bottom: 1px solid #eee; - vertical-align: middle; -} -table tbody tr td.main { - background: #f9f9f9; -} -table tbody tr td.center { - text-align: center; - vertical-align: middle; -} -table tbody tr td.controls { - text-align: center; - font-size: .95em; - color: #888; -} -table tbody tr td.controls img { - margin-bottom: -3px; - margin-right: 1px; -} -table tbody tr td.main a:link, -table tbody tr td.main a:visited, -table tbody tr td.controls a:link, -table tbody tr td.controls a:visited { - text-decoration: none; -} -tr.draft, -tr.excerpt, -tr.draft td, -tr.excerpt td, -tr.draft td.main { - background-color: #dff4ff; - border-color: #c2e1ef !important; - color: #336699; -} -tr.excerpt p { - margin: 0; -} -/* @end */ - -/* @group Preview */ -h1.preview-header { - margin: 0 0 .5em !important; -} -.preview-content { - margin: 0 0 2em; - padding-bottom: .75em; - border-bottom: 1px dotted #ddd; -} -.preview-content ul, -.preview-content ol { - margin: 0 0 1em 2em; - list-style: square; -} -.preview-content ol li { - list-style: decimal; -} -.preview-content a:link, -.preview-content a:visited { - text-decoration: underline; - color: #222; -} -.preview-content hr { - margin: 2em 0; -} -.preview-content blockquote { - margin: 0 2em; - color: #999; -} -/* @end */ - -/* @group Messages */ -p.message { - font-size: 1.1em; - padding: .6em; - margin-bottom: 1.75em; - background: #f1f1f1; - border: 1px solid #ccc; -} -p.message.yay { - background: #189100; - color: #fff; - border-color: #105f00; -} -p.message.boo { - background: #d51800; - color: #fff; - border-color: #9f1000; -} -/* @end */ - -/* @group Buttons */ -/* Inspiration from Chawlk. */ -button, -.button, -a.next_page, -a.prev_page { - display: inline-block; - font-family: Verdana, Helvetica, Arial, sans-serif; - font-weight: bold; - font-size: 1.125em; - margin: 0 .5em 0 0; - color: #333; - padding: .5em .75em; - background: #f1f1f1; - border: 1px solid #ccc; - border-top-color: #f1f1f1; - border-left-color: #f1f1f1; - border-bottom: 1px solid #ccc !important; - cursor: pointer; - text-decoration: none !important; -} -.button { - padding: .6em 1em .5em .9em; -} -button.lite { - padding: .15em .375em .25em .275em; -} -.button.lite, -a.next_page, -a.prev_page { - padding: .1em .4em .2em; -} -button.inline { - position: relative; - top: -1px; - padding: 4px 5px 4px 4px; -} -button.right, -.button.right, -a.next_page { - margin: 0 0 0 .5em; - float: right; -} -button:hover, -.button:hover, -a.next_page:hover, -a.prev_page:hover { - background: #f7f7f7; - border-color: #f7f7f7; - border-bottom-color: #d1d1d1 !important; - border-right-color: #d1d1d1; -} -button:active, -.button:active, -.button.selected, -a.next_page:active, -a.prev_page:active { - background-color: #d7d7d7; - border-color: #d7d7d7; - border-left-color: #b1b1b1; - border-top-color: #b1b1b1; - border-bottom-color: #d7d7d7 !important; -} -button.boo, -.button.boo { - background: #faebe4; - color: #3e3634; - border-color: #faebe4; - border-bottom-color: #d6bdb5; - border-right-color: #d6bdb5; -} -button.boo:hover, -.button.boo:hover { - background: #d51800; - color: #fff; - border-color: #d51800; - border-bottom-color: #9f1000 !important; - border-right-color: #9f1000; -} -button.boo:active, -.button.boo:active { - background: #b30600; - border-color: #b30600; - border-left-color: #7d0000; - border-top-color: #7d0000; - border-bottom-color: #b30600 !important; -} -button.yay, -.button.yay { - background: #ebfae4; - color: #363e34; - border-color: #ebfae4; - border-bottom-color: #bdd6b5; - border-right-color: #bdd6b5; -} -button.yay:hover, -.button.yay:hover { - background: #189100; - color: #fff; - border-color: #189100; - border-bottom-color: #105f00 !important; - border-right-color: #105f00; -} -button.yay:active, -.button.yay:active { - background: #067000; - border-color: #067000; - border-left-color: #003d00; - border-top-color: #003d00; - border-bottom-color: #067000 !important; -} -button[disabled="disabled"], -button.disabled { - background: #f0f0f0; - border-color: #f0f0f0 !important; - color: #999; -} -button[disabled="disabled"]:hover, -button.disabled:hover { - background: #f0f0f0; - border-color: #f0f0f0 !important; - color: #999; - cursor: default; -} -button img, -.button img { - margin: 0 6px -3px -4px; -} -button.lite img, -.button.lite img { - margin: 0 -1px -3px 0; -} -/* @end */ - -/* @group Options */ -.more_options_link { - font-weight: bold; - color: #999; - border-bottom: 1px solid #ddd; - display: block; - text-decoration: none !important; -} -.more_options_link:hover { - color: #666; - border-bottom-color: #aaa; -} -.more_options { - background: #f9f9f9; - padding: 2% 0 0 2%; -} -.more_options p { - width: 48%; - margin: 0 2% 0 0; - min-height: 5.5em; - _height: 5.5em; - float: left; -} -.more_options p input.text { - width: 96.5%; - margin: 0; -} -/* @end */ - -/* @group Page Reordering */ -ul.sort_pages, -ul.sort_pages ul { - padding: 0; - margin: 0 0 0 2em; -} -ul.sort_pages li { - list-style: square; -} -ul.sort_pages li a:link, -ul.sort_pages li a:visited { - text-decoration: none !important; -} -ul.sort_pages input { - font-size: 1em; - margin: .25em .25em .25em 0; -} -ul.sort_pages .sort-placeholder { - border: 1px dashed #777; - display: list-item !important; - margin-bottom: .5em; - height: 1.8em; -} -ul.sort_pages .sort-hover { - border: 1px dashed #777 !important; -} -/* @end */ - -/* @group Helpers & General */ -.breakword { - word-wrap: break-word !important; -} -div.controls.right { - margin-top: -2px; -} -div.controls h4 { - display: inline; -} -div.controls button { - position: relative; - top: -2px; - right: -1px; - margin: 0 0 0 .5em; -} -hr { - border: 0; - border-top: 1px solid #ddd; -} -#content ul li { - list-style: square; -} -.box { - background: #f5f5f5; - border: 1px solid #ddd; - padding: 1em; - margin: 0 0 1em; -} -.box h1 { - font-size: 1.25em !important; - margin: 0 !important; -} -.box h1 .sub { - font-weight: normal; - font-size: .75em; -} -.box h1 span.right { - font-size: .75em; - color: #666; -} -.box h1 span.right a:link, -.box h1 span.right a:visited { - margin-left: 1em; - text-decoration: none; -} -.box h1 span.right a img { - margin-bottom: -3px; -} -.edit_link:hover { - color: #333; -} -.delete_link { - color: #b30600; -} -table tbody td .delete_link { - margin: 0 -.4em 0 0; -} -.delete_link:after { - content: "!"; - opacity: 0; -} -.delete_link:hover { - color: #f00; -} -.delete_link:hover:after { - color: #f00; - - opacity: 1; -} -a.emblem { - border: none; -} -a.emblem img { - margin-bottom: -2px; -} -.pad { - padding: .75em; -} -.margin-right { - margin-right: 1em; -} -.margin-left { - margin-left: 1em; -} -.detail .button.right { - margin-top: 2.25em; -} -.detail h3 { - margin-bottom: .5em !important; -} -.detail.inline { - position: relative; - bottom: -.75em; -} -.wide { - width: 100%; -} -.clear { - clear: both; -} -.left { - float: left !important; -} -.right { - float: right !important; -} -.center { - margin: 0 auto; - text-align: center; -} -.inline { - display: inline; -} -.column { - margin: 0 5em; -} -br#after_options { - display: none; -} -.js_enabled { - display: none; -} -/* @end */ - diff --git a/News/feathers/audio/audio.php b/News/feathers/audio/audio.php deleted file mode 100755 index 4298ecb..0000000 --- a/News/feathers/audio/audio.php +++ /dev/null @@ -1,167 +0,0 @@ -setField(array("attr" => "audio", - "type" => "file", - "label" => __("MP3 File", "audio"), - "note" => "(Max. file size: ".ini_get('upload_max_filesize').")")); - if (isset($_GET['action']) and $_GET['action'] == "bookmarklet") - $this->setField(array("attr" => "from_url", - "type" => "text", - "label" => __("From URL?", "audio"), - "optional" => true, - "no_value" => true)); - $this->setField(array("attr" => "description", - "type" => "text_block", - "label" => __("Description", "audio"), - "optional" => true, - "preview" => true, - "bookmarklet" => "selection")); - - $this->setFilter("description", array("markup_text", "markup_post_text")); - - $this->respondTo("delete_post", "delete_file"); - $this->respondTo("javascript", "player_js"); - $this->respondTo("feed_item", "enclose_mp3"); - $this->respondTo("filter_post", "filter_post"); - $this->respondTo("admin_write_post", "swfupload"); - $this->respondTo("admin_edit_post", "swfupload"); - $this->respondTo("post_options", "add_option"); - } - - public function swfupload($admin, $post = null) { - if (isset($post) and $post->feather != "audio" or - isset($_GET['feather']) and $_GET['feather'] != "audio") - return; - - Trigger::current()->call("prepare_swfupload", "audio", "*.mp3"); - } - - public function submit() { - if (!isset($_POST['filename'])) { - if (isset($_FILES['audio']) and $_FILES['audio']['error'] == 0) - $filename = upload($_FILES['audio'], "mp3"); - elseif (!empty($_POST['from_url'])) - $filename = upload_from_url($_POST['from_url'], "mp3"); - else - error(__("Error"), __("Couldn't upload audio file.")); - } else - $filename = $_POST['filename']; - - return Post::add(array("filename" => $filename, - "description" => $_POST['description']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (!isset($_POST['filename'])) - if (isset($_FILES['audio']) and $_FILES['audio']['error'] == 0) { - $this->delete_file($post); - $filename = upload($_FILES['audio'], "mp3"); - } elseif (!empty($_POST['from_url'])) { - $this->delete_file($post); - $filename = upload_from_url($_POST['from_url'], "mp3"); - } else - $filename = $post->filename; - else { - $this->delete_file($post); - $filename = $_POST['filename']; - } - - $post->update(array("filename" => $filename, - "description" => $_POST['description'])); - } - - public function title($post) { - return oneof($post->title, $post->title_from_excerpt()); - } - - public function excerpt($post) { - return $post->description; - } - - public function feed_content($post) { - return $post->description; - } - - public function delete_file($post) { - if ($post->feather != "audio") return; - unlink(MAIN_DIR.Config::current()->uploads_path.$post->filename); - } - - public function filter_post($post) { - if ($post->feather != "audio") return; - $post->audio_player = $this->flash_player_for($post->filename, array(), $post); - } - - public function player_js() { -?>//'."\n"; - $player.= ''."\n\t"; - $player.= ''."\n\t"; - $player.= ''."\n\t"; - $player.= ''."\n\t"; - $player.= ''."\n\t"; - $player.= ''."\n"; - $player.= ''."\n"; - - return $player; - } - - public function add_option($options, $post = null) { - if (isset($post) and $post->feather != "audio") return; - if (!isset($_GET['feather']) and Config::current()->enabled_feathers[0] != "audio" or - isset($_GET['feather']) and $_GET['feather'] != "audio") return; - - $options[] = array("attr" => "from_url", - "label" => __("From URL?", "audio"), - "type" => "text"); - - return $options; - } - } diff --git a/News/feathers/audio/info.yaml b/News/feathers/audio/info.yaml deleted file mode 100755 index fb365bf..0000000 --- a/News/feathers/audio/info.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Audio -url: http://chyrp.net/ -version: 2.0 -description: An audio feather, including a flash player. -author: - name: Alex Suraci - url: http://ecks.tc/ -uploader: true \ No newline at end of file diff --git a/News/feathers/audio/lib/audio-player.js b/News/feathers/audio/lib/audio-player.js deleted file mode 100755 index 66b35a1..0000000 --- a/News/feathers/audio/lib/audio-player.js +++ /dev/null @@ -1,25 +0,0 @@ -var ap_instances = new Array(); - -function ap_stopAll(playerID) { - for(var i = 0;i, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:16+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/audio/audio.php:6 -msgid "MP3 File" -msgstr "" - -#: feathers/audio/info.yaml:1 -msgid "Audio" -msgstr "" - -#: feathers/audio/info.yaml:6 -msgid "An audio feather, including a flash player." -msgstr "" - -#: feathers/audio/audio.php:17 -msgid "Description" -msgstr "" - -#: feathers/audio/audio.php:11 -#: feathers/audio/audio.php:163 -msgid "From URL?" -msgstr "" - diff --git a/News/feathers/chat/chat.php b/News/feathers/chat/chat.php deleted file mode 100755 index 4c96705..0000000 --- a/News/feathers/chat/chat.php +++ /dev/null @@ -1,132 +0,0 @@ -setField(array("attr" => "title", - "type" => "text", - "label" => __("Title", "chat"), - "optional" => true)); - $this->setField(array("attr" => "dialogue", - "type" => "text_block", - "label" => __("Dialogue", "chat"), - "preview" => true, - "help" => "chat_dialogue", - "bookmarklet" => "selection")); - - $this->customFilter("dialogue", "format_dialogue"); - - $this->setFilter("title", array("markup_title", "markup_post_title")); - $this->setFilter("dialogue", array("markup_text", "markup_post_text")); - - $this->respondTo("preview_chat", "format_dialogue"); - $this->respondTo("help_chat_dialogue", "help"); - } - - public function submit() { - if (empty($_POST['dialogue'])) - error(__("Error"), __("Dialogue can't be blank.")); - - fallback($_POST['slug'], sanitize($_POST['title'])); - - return Post::add(array("title" => $_POST['title'], - "dialogue" => $_POST['dialogue']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (empty($_POST['dialogue'])) - error(__("Error"), __("Dialogue can't be blank.")); - - $post->update(array("title" => $_POST['title'], - "dialogue" => $_POST['dialogue'])); - } - - public function title($post) { - $dialogue = oneof($post->dialogue_unformatted, $post->dialogue); - - $dialogue = explode("\n", $dialogue); - $line = preg_replace("/^\s*[\[\(]?[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?\s*(pm|am)?[\]|\)]?\s*/i", "", $dialogue[0]); - $first_line = preg_replace("/([<]?)([^:|>]+)( \(me\)?)(:|>) (.+)/i", "\\1\\2\\4 \\5", $dialogue[0]); - - return oneof($post->title, $first_line); - } - - public function excerpt($post) { - return $post->dialogue; - } - - public function feed_content($post) { - return $post->dialogue; - } - - public function format_dialogue($text, $post = null) { - if (isset($post)) - $post->dialogue_unformatted = $text; - - $split = explode("\n", $text); - $return = '
      '; - $count = 0; - $my_name = ""; - $links = array(); - foreach ($split as $line) { - # Remove the timstamps - $line = preg_replace("/^\s*[\[\(]?[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?\s*(pm|am)?[\]|\)]?\s*/i", "", $line); - - preg_match("/()\s*(.+)/i", $line, $matches); - - if (empty($matches)) - continue; - - if (preg_match("/\s*\(([^\)]+)\)$/", $matches[2], $attribution)) - if ($attribution[1] == "me") { - $my_name = $matches[2] = str_replace($attribution[0], "", $matches[2]); - } else { - $matches[2] = str_replace($attribution[0], "", $matches[2]); - $links[$matches[2]] = $attribution[1]; - } - - $link = oneof(@$links[$matches[2]], ""); - - $me = ($my_name == $matches[2] ? " me" : ""); - - $username = $matches[1].$matches[2].$matches[3]; - $class = ($count % 2 ? "even" : "odd"); - $return.= '
    • '; - - if (!empty($link)) - $return.= ''.$matches[1].''.fix($matches[2], false).''.$matches[3].' '.$matches[4]."\n"; - else - $return.= ''.fix($username, false).' '.$matches[4]."\n"; - - $return.= '
    • '; - $count++; - } - $return.= "
    "; - - # If they're previewing. - if (!isset($post)) - $return = preg_replace("/(
  • )(.+)(<\/span> (.+)\n<\/li>)/", "\\1\\3\\4", $return); - - return $return; - } - - public function help() { - $title = __("Dialogue Formatting", "chat"); - - $body = "

    ".__("To give yourself a special CSS class, append \" (me)\" to your username, like so:", "chat")."

    \n"; - $body.= "
      \n"; - $body.= "\t
    • "<Alex>" → "<Alex (me)>"
    • \n"; - $body.= "\t
    • "Alex:" → "Alex (me):"
    • \n"; - $body.= "
    \n"; - $body.= "

    ".__("This only has to be done to the first occurrence of the username.", "chat")."

    "; - - $body.= "

    ".__("To attribute a name to a URL, append the URL in parentheses, preceded by a space, to the username:", "chat")."

    \n"; - $body.= "
      \n"; - $body.= "\t
    • "<John>" → "<John (http://example.com/)>"
    • \n"; - $body.= "\t
    • "John:" → "John (http://example.com/):"
    • \n"; - $body.= "
    \n"; - $body.= "

    ".__("This also only has to be done to the first occurrence of the username. It cannot be combined with attributing someone as yourself (because they're already at your site anyway).", "chat")."

    "; - - return array($title, $body); - } - } diff --git a/News/feathers/chat/info.yaml b/News/feathers/chat/info.yaml deleted file mode 100755 index 21e053f..0000000 --- a/News/feathers/chat/info.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Chat -url: http://chyrp.net/ -version: 2.0 -description: Post logs of IRC or other chat formats. -author: - name: Alex Suraci - url: http://ecks.tc/ diff --git a/News/feathers/chat/locale/en_US.pot b/News/feathers/chat/locale/en_US.pot deleted file mode 100644 index 1704c42..0000000 --- a/News/feathers/chat/locale/en_US.pot +++ /dev/null @@ -1,55 +0,0 @@ -# Chyrp v2.1 Translation File. -# Copyright (C) 2011 Chyrp Team -# This file is distributed under the same license as the Chyrp v2.1 package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:16+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/chat/chat.php:123 -msgid "To attribute a name to a URL, append the URL in parentheses, preceded by a space, to the username:" -msgstr "" - -#: feathers/chat/info.yaml:1 -msgid "Chat" -msgstr "" - -#: feathers/chat/chat.php:121 -msgid "This only has to be done to the first occurrence of the username." -msgstr "" - -#: feathers/chat/chat.php:114 -msgid "Dialogue Formatting" -msgstr "" - -#: feathers/chat/chat.php:128 -msgid "This also only has to be done to the first occurrence of the username. It cannot be combined with attributing someone as yourself (because they're already at your site anyway)." -msgstr "" - -#: feathers/chat/chat.php:6 -msgid "Title" -msgstr "" - -#: feathers/chat/info.yaml:5 -msgid "Post logs of IRC or other chat formats." -msgstr "" - -#: feathers/chat/chat.php:116 -msgid "To give yourself a special CSS class, append \" (me)\" to your username, like so:" -msgstr "" - -#: feathers/chat/chat.php:10 -msgid "Dialogue" -msgstr "" - diff --git a/News/feathers/link/info.yaml b/News/feathers/link/info.yaml deleted file mode 100755 index 9091b3b..0000000 --- a/News/feathers/link/info.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Link -url: http://chyrp.net/ -version: 2.0 -description: Link to other sites, name it, and add an optional description. -author: - name: Alex Suraci - url: http://ecks.tc/ diff --git a/News/feathers/link/link.php b/News/feathers/link/link.php deleted file mode 100755 index e4f5c20..0000000 --- a/News/feathers/link/link.php +++ /dev/null @@ -1,72 +0,0 @@ -setField(array("attr" => "source", - "type" => "text", - "label" => __("URL", "link"), - "bookmarklet" => "url")); - $this->setField(array("attr" => "name", - "type" => "text", - "label" => __("Name", "link"), - "bookmarklet" => "title")); - $this->setField(array("attr" => "description", - "type" => "text_block", - "label" => __("Description", "link"), - "optional" => true, - "preview" => true, - "bookmarklet" => "selection")); - - $this->setFilter("name", array("markup_title", "markup_post_title")); - $this->setFilter("description", array("markup_text", "markup_post_text")); - - $this->respondTo("feed_url", "set_feed_url"); - } - - public function submit() { - if (empty($_POST['source'])) - error(__("Error"), __("URL can't be empty.")); - - if (!@parse_url($_POST['source'], PHP_URL_SCHEME)) - $_POST['source'] = "http://".$_POST['source']; - - fallback($_POST['slug'], sanitize($_POST['name'])); - - return Post::add(array("name" => $_POST['name'], - "source" => $_POST['source'], - "description" => $_POST['description']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (empty($_POST['source'])) - error(__("Error"), __("URL can't be empty.")); - - if (!@parse_url($_POST['source'], PHP_URL_SCHEME)) - $_POST['source'] = "http://".$_POST['source']; - - $post->update(array("name" => $_POST['name'], - "source" => $_POST['source'], - "description" => $_POST['description'])); - } - - public function title($post) { - $return = $post->name; - fallback($return, $post->title_from_excerpt()); - fallback($return, $post->source); - return $return; - } - - public function excerpt($post) { - return $post->description; - } - - public function feed_content($post) { - return $post->description; - } - - public function set_feed_url($url, $post) { - if ($post->feather != "link") return; - return $url = $post->source; - } - } diff --git a/News/feathers/link/locale/en_US.pot b/News/feathers/link/locale/en_US.pot deleted file mode 100644 index 5dcf171..0000000 --- a/News/feathers/link/locale/en_US.pot +++ /dev/null @@ -1,39 +0,0 @@ -# Chyrp v2.1 Translation File. -# Copyright (C) 2011 Chyrp Team -# This file is distributed under the same license as the Chyrp v2.1 package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:16+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/link/link.php:10 -msgid "Name" -msgstr "" - -#: feathers/link/link.php:6 -msgid "URL" -msgstr "" - -#: feathers/link/info.yaml:5 -msgid "Link to other sites, name it, and add an optional description." -msgstr "" - -#: feathers/link/info.yaml:1 -msgid "Link" -msgstr "" - -#: feathers/link/link.php:14 -msgid "Description" -msgstr "" - diff --git a/News/feathers/photo/info.yaml b/News/feathers/photo/info.yaml deleted file mode 100755 index f3772de..0000000 --- a/News/feathers/photo/info.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: Photo -url: http://chyrp.net/ -version: 2.0 -description: A photo feather, allowing you to upload any type of picture, with a caption. -author: - name: Alex Suraci - url: http://ecks.tc/ -uploader: true diff --git a/News/feathers/photo/locale/en_US.pot b/News/feathers/photo/locale/en_US.pot deleted file mode 100644 index 68649e7..0000000 --- a/News/feathers/photo/locale/en_US.pot +++ /dev/null @@ -1,47 +0,0 @@ -# Chyrp v2.1 Translation File. -# Copyright (C) 2011 Chyrp Team -# This file is distributed under the same license as the Chyrp v2.1 package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:16+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/photo/info.yaml:6 -msgid "A photo feather, allowing you to upload any type of picture, with a caption." -msgstr "" - -#: feathers/photo/photo.php:143 -msgid "Source" -msgstr "" - -#: feathers/photo/photo.php:138 -msgid "Alt-Text" -msgstr "" - -#: feathers/photo/photo.php:6 -#: feathers/photo/info.yaml:1 -msgid "Photo" -msgstr "" - -#: feathers/photo/photo.php:17 -msgid "Caption" -msgstr "" - -#: feathers/photo/photo.php:11 -#: feathers/photo/photo.php:39 -#: feathers/photo/photo.php:49 -#: feathers/photo/photo.php:148 -msgid "From URL?" -msgstr "" - diff --git a/News/feathers/photo/photo.php b/News/feathers/photo/photo.php deleted file mode 100755 index 58f03f1..0000000 --- a/News/feathers/photo/photo.php +++ /dev/null @@ -1,153 +0,0 @@ -setField(array("attr" => "photo", - "type" => "file", - "label" => __("Photo", "photo"), - "note" => "(Max. file size: ".ini_get('upload_max_filesize').")")); - if (isset($_GET['action']) and $_GET['action'] == "bookmarklet") - $this->setField(array("attr" => "from_url", - "type" => "text", - "label" => __("From URL?", "photo"), - "optional" => true, - "no_value" => true)); - $this->setField(array("attr" => "caption", - "type" => "text_block", - "label" => __("Caption", "photo"), - "optional" => true, - "preview" => true, - "bookmarklet" => "page_link")); - - $this->setFilter("caption", array("markup_text", "markup_post_text")); - - $this->respondTo("delete_post", "delete_file"); - $this->respondTo("filter_post", "filter_post"); - $this->respondTo("post_options", "add_option"); - $this->respondTo("admin_write_post", "swfupload"); - $this->respondTo("admin_edit_post", "swfupload"); - - if (isset($_GET['url']) and - preg_match("/http:\/\/(www\.)?flickr\.com\/photos\/([^\/]+)\/([0-9]+)/", $_GET['url'])) { - $this->bookmarkletSelected(); - - $page = get_remote($_GET['url']); - preg_match("/class=\"photoImgDiv\">\nsetField(array("attr" => "from_url", - "type" => "text", - "label" => __("From URL?", "photo"), - "optional" => true, - "value" => $image[1])); - } - - if (isset($_GET['url']) and preg_match("/\.(jpg|jpeg|png|gif|bmp)$/", $_GET['url'])) { - $this->bookmarkletSelected(); - - $this->setField(array("attr" => "from_url", - "type" => "text", - "label" => __("From URL?", "photo"), - "optional" => true, - "value" => $_GET['url'])); - } - } - - public function swfupload($admin, $post = null) { - if (isset($post) and $post->feather != "photo" or - isset($_GET['feather']) and $_GET['feather'] != "photo") - return; - - Trigger::current()->call("prepare_swfupload", "photo", "*.jpg;*.jpeg;*.png;*.gif;*.bmp"); - } - - public function submit() { - if (!isset($_POST['filename'])) { - if (isset($_FILES['photo']) and $_FILES['photo']['error'] == 0) - $filename = upload($_FILES['photo'], array("jpg", "jpeg", "png", "gif", "bmp")); - elseif (!empty($_POST['from_url'])) - $filename = upload_from_url($_POST['from_url'], array("jpg", "jpeg", "png", "gif", "bmp")); - else - error(__("Error"), __("Couldn't upload photo.")); - } else - $filename = $_POST['filename']; - - return Post::add(array("filename" => $filename, - "caption" => $_POST['caption']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (!isset($_POST['filename'])) - if (isset($_FILES['photo']) and $_FILES['photo']['error'] == 0) { - $this->delete_file($post); - $filename = upload($_FILES['photo'], array("jpg", "jpeg", "png", "gif", "tiff", "bmp")); - } elseif (!empty($_POST['from_url'])) { - $this->delete_file($post); - $filename = upload_from_url($_POST['from_url'], array("jpg", "jpeg", "png", "gif", "tiff", "bmp")); - } else - $filename = $post->filename; - else { - $this->delete_file($post); - $filename = $_POST['filename']; - } - - $post->update(array("filename" => $filename, - "caption" => $_POST['caption'])); - } - - public function title($post) { - return oneof($post->title_from_excerpt(), $post->filename); - } - public function excerpt($post) { - return $post->caption; - } - - public function feed_content($post) { - return self::image_tag($post, 500, 500)."

    ".$post->caption; - } - - public function delete_file($post) { - if ($post->feather != "photo") return; - unlink(MAIN_DIR.Config::current()->uploads_path.$post->filename); - } - - public function filter_post($post) { - if ($post->feather != "photo") return; - $post->image = $this->image_tag($post); - } - - public function image_tag($post, $max_width = 500, $max_height = null, $more_args = "quality=100") { - $filename = $post->filename; - $config = Config::current(); - $alt = !empty($post->alt_text) ? fix($post->alt_text, true) : $filename ; - return ''.$alt.''; - } - - public function image_link($post, $max_width = 500, $max_height = null, $more_args="quality=100") { - $source = !empty($post->source) ? $post->source : uploaded($post->filename) ; - return ''.$this->image_tag($post, $max_width, $max_height, $more_args).''; - } - - public function add_option($options, $post = null) { - if (isset($post) and $post->feather != "photo") return; - if (!isset($_GET['feather']) and Config::current()->enabled_feathers[0] != "photo" or - isset($_GET['feather']) and $_GET['feather'] != "photo") return; - - $options[] = array("attr" => "option[alt_text]", - "label" => __("Alt-Text", "photo"), - "type" => "text", - "value" => oneof(@$post->alt_text, "")); - - $options[] = array("attr" => "option[source]", - "label" => __("Source", "photo"), - "type" => "text", - "value" => oneof(@$post->source, "")); - - $options[] = array("attr" => "from_url", - "label" => __("From URL?", "photo"), - "type" => "text"); - - return $options; - } - } - diff --git a/News/feathers/quote/info.yaml b/News/feathers/quote/info.yaml deleted file mode 100755 index 1882914..0000000 --- a/News/feathers/quote/info.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Quote -url: http://chyrp.net/ -version: 2.0 -description: Post quotes and cite sources. -author: - name: Alex Suraci - url: http://ecks.tc/ diff --git a/News/feathers/quote/locale/en_US.pot b/News/feathers/quote/locale/en_US.pot deleted file mode 100644 index 67208cb..0000000 --- a/News/feathers/quote/locale/en_US.pot +++ /dev/null @@ -1,36 +0,0 @@ -# Chyrp v2.1 Translation File. -# Copyright (C) 2011 Chyrp Team -# This file is distributed under the same license as the Chyrp v2.1 package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:16+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/quote/quote.php:7 -#: feathers/quote/info.yaml:1 -msgid "Quote" -msgstr "" - -#: feathers/quote/info.yaml:5 -msgid "Post quotes and cite sources." -msgstr "" - -#: feathers/quote/quote.php:24 -msgid "Quote can't be empty." -msgstr "" - -#: feathers/quote/quote.php:13 -msgid "Source" -msgstr "" - diff --git a/News/feathers/quote/quote.php b/News/feathers/quote/quote.php deleted file mode 100755 index 21fcf5b..0000000 --- a/News/feathers/quote/quote.php +++ /dev/null @@ -1,59 +0,0 @@ -setField(array("attr" => "quote", - "type" => "text_block", - "rows" => 5, - "label" => __("Quote", "quote"), - "preview" => true, - "bookmarklet" => "selection")); - $this->setField(array("attr" => "source", - "type" => "text_block", - "rows" => 5, - "label" => __("Source", "quote"), - "optional" => true, - "preview" => true, - "bookmarklet" => "page_link")); - - $this->setFilter("quote", array("markup_text", "markup_post_text")); - $this->setFilter("source", array("markup_text", "markup_post_text")); - } - - public function submit() { - if (empty($_POST['quote'])) - error(__("Error"), __("Quote can't be empty.", "quote")); - - return Post::add(array("quote" => $_POST['quote'], - "source" => $_POST['source']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (empty($_POST['quote'])) - error(__("Error"), __("Quote can't be empty.")); - - $post->update(array("quote" => $_POST['quote'], - "source" => $_POST['source'])); - } - - public function title($post) { - return $post->title_from_excerpt(); - } - - public function excerpt($post) { - return $post->quote; - } - - public function add_dash($text) { - return preg_replace("/(]+)?>|^)/si", "\\1— ", $text, 1); - } - - public function feed_content($post) { - $body = "
    \n\t"; - $body.= $post->quote; - $body.= "\n
    \n"; - $body.= $post->source; - return $body; - } - } diff --git a/News/feathers/text/info.yaml b/News/feathers/text/info.yaml deleted file mode 100755 index e94e6d5..0000000 --- a/News/feathers/text/info.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Text -url: http://chyrp.net/ -version: 2.0 -description: A basic text feather. -author: - name: Alex Suraci - url: http://ecks.tc/ diff --git a/News/feathers/text/locale/en_US.pot b/News/feathers/text/locale/en_US.pot deleted file mode 100644 index 1942e7f..0000000 --- a/News/feathers/text/locale/en_US.pot +++ /dev/null @@ -1,35 +0,0 @@ -# Chyrp v2.1 Translation File. -# Copyright (C) 2011 Chyrp Team -# This file is distributed under the same license as the Chyrp v2.1 package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:17+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/text/info.yaml:1 -msgid "Text" -msgstr "" - -#: feathers/text/text.php:11 -msgid "Body" -msgstr "" - -#: feathers/text/info.yaml:5 -msgid "A basic text feather." -msgstr "" - -#: feathers/text/text.php:6 -msgid "Title" -msgstr "" - diff --git a/News/feathers/text/text.php b/News/feathers/text/text.php deleted file mode 100755 index 4d1ba24..0000000 --- a/News/feathers/text/text.php +++ /dev/null @@ -1,50 +0,0 @@ -setField(array("attr" => "title", - "type" => "text", - "label" => __("Title", "text"), - "optional" => true, - "bookmarklet" => "title")); - $this->setField(array("attr" => "body", - "type" => "text_block", - "label" => __("Body", "text"), - "preview" => true, - "bookmarklet" => "selection")); - - $this->setFilter("title", array("markup_title", "markup_post_title")); - $this->setFilter("body", array("markup_text", "markup_post_text")); - } - - public function submit() { - if (empty($_POST['body'])) - error(__("Error"), __("Body can't be blank.")); - - fallback($_POST['slug'], sanitize($_POST['title'])); - - return Post::add(array("title" => $_POST['title'], - "body" => $_POST['body']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (empty($_POST['body'])) - error(__("Error"), __("Body can't be blank.")); - - $post->update(array("title" => $_POST['title'], - "body" => $_POST['body'])); - } - - public function title($post) { - return oneof($post->title, $post->title_from_excerpt()); - } - - public function excerpt($post) { - return $post->body; - } - - public function feed_content($post) { - return $post->body; - } - } diff --git a/News/feathers/video/info.yaml b/News/feathers/video/info.yaml deleted file mode 100755 index a6c9740..0000000 --- a/News/feathers/video/info.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Video -url: http://chyrp.net/ -version: 2.0 -description: Lets you post videos to your site. -author: - name: Alex Suraci - url: http://ecks.tc/ diff --git a/News/feathers/video/locale/en_US.pot b/News/feathers/video/locale/en_US.pot deleted file mode 100644 index 39cda94..0000000 --- a/News/feathers/video/locale/en_US.pot +++ /dev/null @@ -1,32 +0,0 @@ -# Chyrp v2.1 Translation File. -# Copyright (C) 2011 Chyrp Team -# This file is distributed under the same license as the Chyrp v2.1 package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: Chyrp v2.1\n" -"Report-Msgid-Bugs-To: email@chyrp.net\n" -"POT-Creation-Date: 2011-01-10 22:17+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FIRST LAST \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: feathers/video/info.yaml:5 -msgid "Lets you post videos to your site." -msgstr "" - -#: feathers/video/video.php:7 -#: feathers/video/info.yaml:1 -msgid "Video" -msgstr "" - -#: feathers/video/video.php:15 -msgid "Caption" -msgstr "" - diff --git a/News/feathers/video/video.php b/News/feathers/video/video.php deleted file mode 100755 index 7671096..0000000 --- a/News/feathers/video/video.php +++ /dev/null @@ -1,125 +0,0 @@ -setField(array("attr" => "video", - "type" => "text_block", - "rows" => 4, - "label" => __("Video", "video"), - "preview" => true, - "bookmarklet" => $this->isVideo() ? - "url" : - "")); - $this->setField(array("attr" => "caption", - "type" => "text_block", - "rows" => 4, - "label" => __("Caption", "video"), - "optional" => true, - "preview" => true, - "bookmarklet" => "selection")); - - if ($this->isVideo()) - $this->bookmarkletSelected(); - - $this->setFilter("caption", array("markup_text", "markup_post_text")); - - $this->respondTo("preview_video", "embed_tag"); - } - - public function submit() { - if (empty($_POST['video'])) - error(__("Error"), __("Video can't be blank.")); - - return Post::add(array("embed" => $this->embed_tag($_POST['video']), - "video" => $_POST['video'], - "caption" => $_POST['caption']), - $_POST['slug'], - Post::check_url($_POST['slug'])); - } - - public function update($post) { - if (empty($_POST['video'])) - error(__("Error"), __("Video can't be blank.")); - - $post->update(array("embed" => $this->embed_tag($_POST['video']), - "video" => $_POST['video'], - "caption" => $_POST['caption'])); - } - - public function title($post) { - return $post->title_from_excerpt(); - } - - public function excerpt($post) { - return $post->caption; - } - - public function feed_content($post) { - return $post->embed."

    ".$post->caption; - } - - public function embed_tag($video, $field = null) { # We use this for previewing too - if (isset($field) and $field != "embed") - return $video; # If they're previewing and the field argument isn't the embed, return the original. - - if (preg_match("/http:\/\/(www\.|[a-z]{2}\.)?youtube\.com\/watch\?v=([^&]+)/", $video, $matches)) { - return ''; - } else if (preg_match("/^http:\/\/(www\.)?vimeo.com\/([0-9]+)/", $video, $matches)) { - $site = get_remote("http://vimeo.com/".$matches[2]); - preg_match('/
    /', - $site, - $scale); - return ''; - } else if (preg_match("/http:\/\/(www\.)?metacafe.com\/watch\/([0-9]+)\/([^\/&\?]+)/", $video, $matches)) { - return ''; - } else if (preg_match("/http:\/\/(www\.)?revver.com\/video\/([0-9]+)/", $video, $matches)) { - return ''; - } else if (preg_match("/http:\/\/(www\.)viddler\.com\/.+/", $video)) { - $viddler_page = get_remote($video); - - if (preg_match("/'; - } - - return $video; - } - - return $video; - } - - public function embed_tag_for($post, $max_width = 500) { - $post->embed = preg_replace("/&([[:alnum:]_]+)=/", "&\\1=", $post->embed); - - if (preg_match("/width(=\"|='|:\s*)([0-9]+)/", $post->embed, $width)) { - $sep_w = $width[1]; - $original_width = $width[2]; - } else - return $post->embed; - - if (preg_match("/height(=\"|='|:\s*)([0-9]+)/", $post->embed, $height)) { - $sep_h = $height[1]; - $original_height = $height[2]; - - $new_height = (int) (($max_width / $original_width) * $original_height); - } - - $post->embed = str_replace(array($width[0], $height[0]), array("width".$sep_w.$max_width, "height".$sep_h.$new_height), $post->embed); - - return $post->embed; - } - - public function isVideo() { - if (!isset($_GET['url'])) - return false; - - if (preg_match("/http:\/\/(www\.|[a-z]{2}\.)?youtube\.com\/watch\?v=([^&]+)/", $_GET['url']) or - preg_match("/http:\/\/(www\.)?vimeo.com\/([0-9]+)/", $_GET['url']) or - preg_match('/http:\/\/(www\.)?metacafe.com\/watch\/([0-9]+)\/([^\/&\?]+)/', $_GET['url']) or - preg_match("/http:\/\/(www\.)?revver.com\/video\/([0-9]+)/", $_GET['url']) or - preg_match("/http:\/\/(www\.)viddler\.com\/.+/", $_GET['url'])) - return true; - - return false; - } - } diff --git a/News/includes/admin.js.php b/News/includes/admin.js.php deleted file mode 100644 index 9037a4a..0000000 --- a/News/includes/admin.js.php +++ /dev/null @@ -1,741 +0,0 @@ - - diff --git a/News/includes/ajax.php b/News/includes/ajax.php deleted file mode 100755 index bcfe753..0000000 --- a/News/includes/ajax.php +++ /dev/null @@ -1,207 +0,0 @@ -group->can("view_site")) - if ($trigger->exists("can_not_view_site")) - $trigger->call("can_not_view_site"); - else - show_403(__("Access Denied"), __("You are not allowed to view this site.")); - - switch($_POST['action']) { - case "edit_post": - if (!isset($_POST['id'])) - error(__("No ID Specified"), __("Please specify an ID of the post you would like to edit.")); - - $post = new Post($_POST['id'], array("filter" => false, "drafts" => true)); - - if ($post->no_results) { - header("HTTP/1.1 404 Not Found"); - $trigger->call("not_found"); - exit; - } - - if (!$post->editable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit posts.")); - - $title = $post->title(); - $theme_file = THEME_DIR."/forms/feathers/".$post->feather.".php"; - $default_file = FEATHERS_DIR."/".$post->feather."/fields.php"; - - $options = array(); - Trigger::current()->filter($options, array("edit_post_options", "post_options"), $post); - - $main->display("forms/post/edit", array("post" => $post, - "feather" => Feathers::$instances[$post->feather], - "options" => $options, - "groups" => Group::find(array("order" => "id ASC")))); - break; - - case "delete_post": - $post = new Post($_POST['id'], array("drafts" => true)); - - if ($post->no_results) { - header("HTTP/1.1 404 Not Found"); - $trigger->call("not_found"); - exit; - } - - if (!$post->deletable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete this post.")); - - Post::delete($_POST['id']); - break; - - case "view_post": - fallback($_POST['offset'], 0); - fallback($_POST['context']); - - $reason = (isset($_POST['reason'])) ? $_POST['reason'] : "" ; - - if (isset($_POST['id'])) - $post = new Post($_POST['id'], array("drafts" => true)); - - if ($post->no_results) { - header("HTTP/1.1 404 Not Found"); - $trigger->call("not_found"); - exit; - } - - $main->display("feathers/".$post->feather, array("post" => $post, "ajax_reason" => $reason)); - break; - - case "preview": - if (empty($_POST['content'])) - break; - - $trigger->filter($_POST['content'], - array("preview_".$_POST['feather'], "preview"), - $_POST['field'], - $_POST['feather']); - - echo "

    ".__("Preview")."

    \n". - "
    ".fix($_POST['content'])."
    "; - break; - - case "check_confirm": - if (!$visitor->group->can("toggle_extensions")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable extensions.")); - - $dir = ($_POST['type'] == "module") ? MODULES_DIR : FEATHERS_DIR ; - $info = YAML::load($dir."/".$_POST['check']."/info.yaml"); - fallback($info["confirm"], ""); - - if (!empty($info["confirm"])) - echo __($info["confirm"], $_POST['check']); - - break; - - case "organize_pages": - foreach ($_POST['parent'] as $id => $parent) - $sql->update("pages", array("id" => $id), array("parent_id" => $parent)); - - foreach ($_POST['page_list'] as $index => $page) - $sql->update("pages", array("id" => $page), array("list_order" => $index)); - - break; - - case "enable_module": case "enable_feather": - $type = ($_POST['action'] == "enable_module") ? "module" : "feather" ; - - if (!$visitor->group->can("change_settings")) - if ($type == "module") - exit("{ \"notifications\": [\"".__("You do not have sufficient privileges to enable/disable modules.")."\"] }"); - else - exit("{ \"notifications\": [\"".__("You do not have sufficient privileges to enable/disable feathers.")."\"] }"); - - if (($type == "module" and module_enabled($_POST['extension'])) or - ($type == "feather" and feather_enabled($_POST['extension']))) - exit("{ \"notifications\": [] }"); - - $enabled_array = ($type == "module") ? "enabled_modules" : "enabled_feathers" ; - $folder = ($type == "module") ? MODULES_DIR : FEATHERS_DIR ; - - if (file_exists($folder."/".$_POST["extension"]."/locale/".$config->locale.".mo")) - load_translator($_POST["extension"], $folder."/".$_POST["extension"]."/locale/".$config->locale.".mo"); - - $info = YAML::load($folder."/".$_POST["extension"]."/info.yaml"); - fallback($info["uploader"], false); - fallback($info["notifications"], array()); - - foreach ($info["notifications"] as &$notification) - $notification = addslashes(__($notification, $_POST["extension"])); - - require $folder."/".$_POST["extension"]."/".$_POST["extension"].".php"; - - if ($info["uploader"]) - if (!file_exists(MAIN_DIR.$config->uploads_path)) - $info["notifications"][] = _f("Please create the %s directory at your Chyrp install's root and CHMOD it to 777.", array($config->uploads_path)); - elseif (!is_writable(MAIN_DIR.$config->uploads_path)) - $info["notifications"][] = _f("Please CHMOD %s to 777.", array($config->uploads_path)); - - $class_name = camelize($_POST["extension"]); - - if ($type == "module" and !is_subclass_of($class_name, "Modules")) - error("", __("Item is not a module.")); - - if ($type == "feather" and !is_subclass_of($class_name, "Feathers")) - error("", __("Item is not a feather.")); - - if (method_exists($class_name, "__install")) - call_user_func(array($class_name, "__install")); - - $new = $config->$enabled_array; - array_push($new, $_POST["extension"]); - $config->set($enabled_array, $new); - - exit('{ "notifications": ['. - (!empty($info["notifications"]) ? '"'.implode('", "', $info["notifications"]).'"' : ""). - '] }'); - - break; - - case "disable_module": case "disable_feather": - $type = ($_POST['action'] == "disable_module") ? "module" : "feather" ; - - if (!$visitor->group->can("change_settings")) - if ($type == "module") - exit("{ \"notifications\": [\"".__("You do not have sufficient privileges to enable/disable modules.")."\"] }"); - else - exit("{ \"notifications\": [\"".__("You do not have sufficient privileges to enable/disable feathers.")."\"] }"); - - if (($type == "module" and !module_enabled($_POST['extension'])) or - ($type == "feather" and !feather_enabled($_POST['extension']))) - exit("{ \"notifications\": [] }"); - - $class_name = camelize($_POST["extension"]); - if (method_exists($class_name, "__uninstall")) - call_user_func(array($class_name, "__uninstall"), ($_POST['confirm'] == "1")); - - $enabled_array = ($type == "module") ? "enabled_modules" : "enabled_feathers" ; - $config->set($enabled_array, - array_diff($config->$enabled_array, array($_POST['extension']))); - - exit('{ "notifications": [] }'); - - break; - - case "reorder_feathers": - $reorder = oneof(@$_POST['list'], $config->enabled_feathers); - foreach ($reorder as &$value) - $value = preg_replace("/feathers\[([^\]]+)\]/", "\\1", $value); - - $config->set("enabled_feathers", $reorder); - break; - } - - $trigger->call("ajax"); - - if (!empty($_POST['action'])) - $trigger->call("ajax_".$_POST['action']); diff --git a/News/includes/caches/.gitignore b/News/includes/caches/.gitignore deleted file mode 100644 index 72e8ffc..0000000 --- a/News/includes/caches/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/News/includes/class/Config.php b/News/includes/class/Config.php deleted file mode 100755 index a7e1cbc..0000000 --- a/News/includes/class/Config.php +++ /dev/null @@ -1,114 +0,0 @@ - $val array. - private $yaml = array(); - - /** - * Function: __construct - * Loads the configuration YAML file. - */ - private function __construct() { - if (!file_exists(INCLUDES_DIR."/config.yaml.php")) - return false; - - $contents = str_replace("\n", - "", - file_get_contents(INCLUDES_DIR."/config.yaml.php")); - - $this->yaml = YAML::load($contents); - - $arrays = array("enabled_modules", "enabled_feathers", "routes"); - foreach ($this->yaml as $setting => $value) - if (in_array($setting, $arrays) and empty($value)) - $this->$setting = array(); - elseif (!is_int($setting)) - $this->$setting = (is_string($value)) ? stripslashes($value) : $value ; - - fallback($this->url, $this->chyrp_url); - } - - /** - * Function: set - * Adds or replaces a configuration setting with the given value. - * - * Parameters: - * $setting - The setting name. - * $value - The value. - * $overwrite - If the setting exists and is the same value, should it be overwritten? - */ - public function set($setting, $value, $overwrite = true) { - if (isset($this->$setting) and $this->$setting == $value and !$overwrite) - return false; - - if (isset($this->file) and file_exists($this->file)) { - $contents = str_replace("\n", - "", - file_get_contents($this->file)); - - $this->yaml = YAML::load($contents); - } - - # Add the setting - $this->yaml[$setting] = $this->$setting = $value; - - if (class_exists("Trigger")) - Trigger::current()->call("change_setting", $setting, $value, $overwrite); - - # Add the PHP protection! - $contents = "\n"; - - # Generate the new YAML settings - $contents.= YAML::dump($this->yaml); - - if (!@file_put_contents(INCLUDES_DIR."/config.yaml.php", $contents)) { - Flash::warning(_f("Could not set \"%s\" configuration setting because %s is not writable.", - array($setting, "/includes/config.yaml.php"))); - return false; - } else - return true; - } - - /** - * Function: remove - * Removes a configuration setting. - * - * Parameters: - * $setting - The name of the setting to remove. - */ - public function remove($setting) { - if (isset($this->file) and file_exists($this->file)) { - $contents = str_replace("\n", - "", - file_get_contents($this->file)); - - $this->yaml = YAML::load($contents); - } - - # Add the setting - unset($this->yaml[$setting]); - - # Add the PHP protection! - $contents = "\n"; - - # Generate the new YAML settings - $contents.= YAML::dump($this->yaml); - - file_put_contents(INCLUDES_DIR."/config.yaml.php", $contents); - } - - /** - * Function: current - * Returns a singleton reference to the current configuration. - */ - public static function & current() { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } diff --git a/News/includes/class/Feathers.php b/News/includes/class/Feathers.php deleted file mode 100755 index e8b72f9..0000000 --- a/News/includes/class/Feathers.php +++ /dev/null @@ -1,106 +0,0 @@ - - */ - protected function setFilter($field, $name) { - self::$filters[get_class($this)][] = array("field" => $field, "name" => $name); - } - - /** - * Function: customFilter - * Allows a Feather to apply its own filter to a specified field. - * - * Parameters: - * $field - Attribute of the post to filter. - * $name - Name of the class function to use as the filter. - * $priority - Priority of the filter. - * - * See Also: - * - */ - protected function customFilter($field, $name, $priority = 10) { - self::$custom_filters[get_class($this)][] = array("field" => $field, "name" => $name); - } - - /** - * Function: respondTo - * Allows a Feather to respond to a Trigger as a Module would. - * - * Parameters: - * $name - Name of the trigger to respond to. - * $function - Name of the class function to respond with. - * $priority - Priority of the response. - * - * See Also: - * - */ - protected function respondTo($name, $function = null, $priority = 10) { - fallback($function, $name); - Trigger::current()->priorities[$name][] = array("priority" => $priority, "function" => array($this, $function)); - } - - /** - * Function: setField - * Sets the feather's fields for creating/editing posts with that feather. - * - * Parameters: - * $options - An array of key => val options for the field. - * - * Options: - * attr - The technical name for the field. Think $post->attr. - * type - The field type. (text, file, text_block, or select) - * label - The label for the field. - * preview - Is this field previewable? - * optional - Is this field optional? - * bookmarklet - What to fill this field by in the bookmarklet. - * url or page_url - The URL of the page they're viewing when they open the bookmarklet. - * title or page_title - The title of the page they're viewing when they open the bookmarklet. - * selection - Their selection on the page they're viewing when they open the bookmarklet. - * extra - Stuff to output after the input field. Can be anything. - * note - A minor note to display next to the label text. - */ - protected function setField($options) { - fallback($options["classes"], array()); - - if (isset($options["class"])) - $options["classes"][] = $options["class"]; - - if (isset($options["preview"]) and $options["preview"]) - $options["classes"][] = "preview_me"; - - $this->fields[$options["attr"]] = $options; - } - - /** - * Function: bookmarkletSelected - * The Feather that this function is called from will be selected when they open the Bookmarklet. - */ - protected function bookmarkletSelected() { - AdminController::current()->selected_bookmarklet = $this->safename; - } - } diff --git a/News/includes/class/Flash.php b/News/includes/class/Flash.php deleted file mode 100644 index 85be928..0000000 --- a/News/includes/class/Flash.php +++ /dev/null @@ -1,197 +0,0 @@ - false, - "notice" => false, - "warning" => false, - null => false); - - /** - * Function: __construct - * Removes empty notification variables from the session. - */ - private function __construct() { - foreach (array("messages", "notices", "warnings") as $type) - if (isset($_SESSION[$type]) and empty($_SESSION[$type])) - unset($_SESSION[$type]); - } - - /** - * Function: prepare - * Prepare the structure of the "flash" session value. - */ - static function prepare($type) { - if (!isset($_SESSION)) - $_SESSION = array(); - - if (!isset($_SESSION[$type])) - $_SESSION[$type] = array(); - } - - /** - * Function: message - * Add a message (neutral) to the session. - * - * Parameters: - * $message - Message to display. - * $redirect_to - URL to redirect to after the message is stored. - */ - static function message($message, $redirect_to = null) { - self::prepare("messages"); - - $_SESSION['messages'][] = Trigger::current()->filter($message, "flash_message", $redirect_to); - - if (isset($redirect_to)) - redirect($redirect_to); - } - - /** - * Function: notice - * Add a notice (positive) message to the session. - * - * Parameters: - * $message - Message to display. - * $redirect_to - URL to redirect to after the message is stored. - */ - static function notice($message, $redirect_to = null) { - self::prepare("notices"); - - $_SESSION['notices'][] = Trigger::current()->filter($message, "flash_notice_message", $redirect_to); - - if (TESTER) - exit("SUCCESS: ".$message); - - if (isset($redirect_to)) - redirect($redirect_to); - } - - /** - * Function: warning - * Add a warning (negative) message to the session. - * - * Parameters: - * $message - Message to display. - * $redirect_to - URL to redirect to after the message is stored. - */ - static function warning($message, $redirect_to = null) { - self::prepare("warnings"); - - $_SESSION['warnings'][] = Trigger::current()->filter($message, "flash_warning_message", $redirect_to); - - if (TESTER) - exit("ERROR: ".$message); - - if (isset($redirect_to)) - redirect($redirect_to); - } - - /** - * Function: messages - * Calls "messages". - */ - public function messages() { - return $this->serve("messages"); - } - - /** - * Function: notices - * Calls "notices". - */ - public function notices() { - return $this->serve("notices"); - } - - /** - * Function: warnings - * Calls "warnings". - */ - public function warnings() { - return $this->serve("warnings"); - } - - /** - * Function: all - * Returns an associative array of all messages and destroys their session values. - * - * Returns: - * An array of every message available, in the form of [type => [messages]]. - */ - public function all() { - return array("messages" => $this->messages(), - "notices" => $this->notices(), - "warnings" => $this->warnings()); - } - - /** - * Function: serve - * Serves a message of type $type and destroys it from the session. - * - * Parameters: - * $type - Type of messages to serve. - * - * Returns: - * An array of messages of the requested type. - */ - public function serve($type) { - if (!empty($_SESSION[$type])) - self::$exists[depluralize($type)] = self::$exists[null] = true; - - if (isset($_SESSION[$type])) { - $this->$type = $_SESSION[$type]; - $_SESSION[$type] = array(); - } - - return $this->$type; - } - - /** - * Function: exists - * Checks for flash messages. - * - * Parameters: - * $type - The type of message to check for. - */ - static function exists($type = null) { - if (self::$exists[$type]) - return self::$exists[$type]; - - if (isset($type)) - return self::$exists[$type] = !empty($_SESSION[pluralize($type)]); - else - foreach (array("messages", "notices", "warnings") as $type) - if (!empty($_SESSION[$type])) - return self::$exists[depluralize($type)] = self::$exists[null] = true; - - return false; - } - - /** - * Function: current - * Returns a singleton reference to the current class. - */ - public static function & current() { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } diff --git a/News/includes/class/Model.php b/News/includes/class/Model.php deleted file mode 100644 index 7f4cc1c..0000000 --- a/News/includes/class/Model.php +++ /dev/null @@ -1,465 +0,0 @@ -__placeholders) and $this->__placeholders); - - Trigger::current()->filter($filtered, $model_name."_".$name."_attr", $this); - if ($filtered !== false) - $this->$name = $filtered; - - $this->belongs_to = (array) $this->belongs_to; - $this->has_many = (array) $this->has_many; - $this->has_one = (array) $this->has_one; - - if (in_array($name, $this->belongs_to) or isset($this->belongs_to[$name])) { - $class = (isset($this->belongs_to[$name])) ? $this->belongs_to[$name] : $name ; - if (isset($this->belongs_to[$name])) { - $opts =& $this->belongs_to[$name]; - $model = oneof(@$opts["model"], $name); - - if (preg_match("/^\(([a-z0-9_]+)\)$/", $model, $match)) - $model = $this->$match[1]; - - $match = oneof(@$opts["by"], strtolower($name)); - - fallback($opts["where"], array("id" => $this->{$match."_id"})); - - $opts["where"] = (array) $opts["where"]; - foreach ($opts["where"] as &$val) - if (preg_match("/^\(([a-z0-9_]+)\)$/", $val, $match)) - $val = $this->$match[1]; - - fallback($opts["placeholders"], $placeholders); - } else { - $model = $name; - $opts = array("where" => array("id" => $this->{$name."_id"})); - } - - return $this->$name = new $model(null, $opts); - } elseif (in_array($name, $this->has_many) or isset($this->has_many[$name])) { - if (isset($this->has_many[$name])) { - $opts =& $this->has_many[$name]; - $model = oneof(@$opts["model"], depluralize($name)); - - if (preg_match("/^\(([a-z0-9_]+)\)$/", $model, $match)) - $model = $this->$match[1]; - - $match = oneof(@$opts["by"], strtolower($name)); - - fallback($opts["where"], array($match."_id" => $this->id)); - - $opts["where"] = (array) $opts["where"]; - foreach ($opts["where"] as &$val) - if (preg_match("/^\(([a-z0-9_]+)\)$/", $val, $match)) - $val = $this->$match[1]; - - fallback($opts["placeholders"], $placeholders); - } else { - $model = depluralize($name); - $match = $model_name; - $opts = array("where" => array(strtolower($match)."_id" => $this->id), - "placeholders" => $placeholders); - } - - return $this->$name = call_user_func(array($model, "find"), $opts); - } elseif (in_array($name, $this->has_one) or isset($this->has_one[$name])) { - if (isset($this->has_one[$name])) { - $opts =& $this->has_one[$name]; - $model = oneof(@$opts["model"], depluralize($name)); - - if (preg_match("/^\(([a-z0-9_]+)\)$/", $model, $match)) - $model = $this->$match[1]; - - $match = oneof(@$opts["by"], strtolower($name)); - - fallback($opts["where"], array($match."_id" => $this->id)); - - $opts["where"] = (array) $opts["where"]; - foreach ($opts["where"] as &$val) - if (preg_match("/^\(([a-z0-9_]+)\)$/", $val, $match)) - $val = $this->$match[1]; - } else { - $model = depluralize($name); - $match = $model_name; - $opts = array("where" => array(strtolower($match)."_id" => $this->id)); - } - - return $this->$name = new $model(null, $opts); - } - - if (isset($this->$name)) - return $this->$name; - } - - /** - * Function: __getPlaceholders - * Calls __get with the requested $name, but grabs everything as placeholders. - * - * Parameters: - * $name - Name to call with. - * - * Returns: - * @mixed@ - * - * See Also: - * - */ - public function __getPlaceholders($name) { - $this->__placeholders = true; - $return = $this->__get($name); - unset($this->__placeholders); - return $return; - } - - /** - * Function: grab - * Grabs a single model from the database. - * - * Parameters: - * $model - The instantiated model class to pass the object to (e.g. Post). - * $id - The ID of the model to grab. Can be null. - * $options - An array of options, mostly SQL things. - * - * Options: - * select - What to grab from the table. @(modelname)s@ by default. - * from - Which table(s) to grab from? @(modelname)s.*@ by default. - * left_join - A @LEFT JOIN@ associative array. Example: @array("table" => "foo", "where" => "foo = :bar")@ - * where - A string or array of conditions. @array("__(modelname)s.id = :id")@ by default. - * params - An array of parameters to pass to PDO. @array(":id" => $id)@ by default. - * group - A string or array of "GROUP BY" conditions. - * order - What to order the SQL result by. @__(modelname)s.id DESC@ by default. - * offset - Offset for SQL query. - * read_from - An array to read from instead of performing another query. - */ - protected static function grab($model, $id, $options = array()) { - $model_name = strtolower(get_class($model)); - - if ($model_name == "visitor") - $model_name = "user"; - - if (!isset($id) and isset($options["where"]["id"])) - $id = $options["where"]["id"]; - - $cache = (is_numeric($id) and isset(self::$caches[$model_name][$id])) ? - self::$caches[$model_name][$id] : - ((isset($options["read_from"]["id"]) and isset(self::$caches[$model_name][$options["read_from"]["id"]])) ? - self::$caches[$model_name][$options["read_from"]["id"]] : - (isset(self::$caches[$model_name][serialize($id)]) ? - self::$caches[$model_name][serialize($id)] : - array())) ; - - # Is this model already in the cache? - if (!empty($cache)) { - foreach ($cache as $attr => $val) - $model->$attr = $val; - - return; - } - - fallback($options["select"], "*"); - fallback($options["from"], ($model_name == "visitor" ? "users" : pluralize($model_name))); - fallback($options["left_join"], array()); - fallback($options["where"], array()); - fallback($options["params"], array()); - fallback($options["group"], array()); - fallback($options["order"], "id DESC"); - fallback($options["offset"], null); - fallback($options["read_from"], array()); - fallback($options["ignore_dupes"], array()); - - $options["where"] = (array) $options["where"]; - $options["from"] = (array) $options["from"]; - $options["select"] = (array) $options["select"]; - - if (is_numeric($id)) - $options["where"]["id"] = $id; - elseif (is_array($id)) - $options["where"] = array_merge($options["where"], $id); - - $trigger = Trigger::current(); - $trigger->filter($options, $model_name."_grab"); - - $sql = SQL::current(); - if (!empty($options["read_from"])) - $read = $options["read_from"]; - else { - $query = $sql->select($options["from"], - $options["select"], - $options["where"], - $options["order"], - $options["params"], - null, - $options["offset"], - $options["group"], - $options["left_join"]); - $all = $query->fetchAll(); - - if (count($all) == 1) - $read = $all[0]; - else { - $merged = array(); - - foreach ($all as $index => $row) - foreach ($row as $column => $val) - $merged[$row["id"]][$column][] = $val; - - foreach ($all as $index => &$row) - $row = $merged[$row["id"]]; - - if (count($all)) { - $keys = array_keys($all); - $read = $all[$keys[0]]; - foreach ($read as $name => &$column) { - $column = (!in_array($name, $options["ignore_dupes"]) ? - array_unique($column) : - $column); - $column = (count($column) == 1) ? - $column[0] : - $column ; - } - } else - $read = false; - } - } - - if (!count($read) or !$read) - return $model->no_results = true; - else - $model->no_results = false; - - foreach ($read as $key => $val) - if (!is_int($key)) - $model->$key = $val; - - if (isset($query) and isset($query->queryString)) - $model->queryString = $query->queryString; - - if (isset($model->updated_at)) - $model->updated = (!empty($model->updated_at) and $model->updated_at != "0000-00-00 00:00:00"); - - $clone = clone $model; - - self::$caches[$model_name][$read["id"]] = $clone; - - if (!is_numeric($id) and !isset($options["read_from"]["id"]) and $id !== null) - self::$caches[$model_name][serialize($id)] = $clone; - } - - /** - * Function: search - * Returns an array of model objects that are found by the $options array. - * - * Parameters: - * $options - An array of options, mostly SQL things. - * $options_for_object - An array of options for the instantiation of the model. - * - * Options: - * select - What to grab from the table. @(modelname)s@ by default. - * from - Which table(s) to grab from? @(modelname)s.*@ by default. - * left_join - A @LEFT JOIN@ associative array. Example: @array("table" => "foo", "where" => "foo = :bar")@ - * where - A string or array of conditions. @array("__(modelname)s.id = :id")@ by default. - * params - An array of parameters to pass to PDO. @array(":id" => $id)@ by default. - * group - A string or array of "GROUP BY" conditions. - * order - What to order the SQL result by. @__(modelname)s.id DESC@ by default. - * offset - Offset for SQL query. - * limit - Limit for SQL query. - * - * See Also: - * - */ - protected static function search($model, $options = array(), $options_for_object = array()) { - $model_name = strtolower($model); - - fallback($options["select"], "*"); - fallback($options["from"], pluralize(strtolower($model))); - fallback($options["left_join"], array()); - fallback($options["where"], null); - fallback($options["params"], array()); - fallback($options["group"], array()); - fallback($options["order"], "id DESC"); - fallback($options["offset"], null); - fallback($options["limit"], null); - fallback($options["placeholders"], false); - fallback($options["ignore_dupes"], array()); - - $options["where"] = (array) $options["where"]; - $options["from"] = (array) $options["from"]; - $options["select"] = (array) $options["select"]; - - $trigger = Trigger::current(); - $trigger->filter($options, pluralize(strtolower($model_name))."_get"); - - $grab = SQL::current()->select($options["from"], - $options["select"], - $options["where"], - $options["order"], - $options["params"], - $options["limit"], - $options["offset"], - $options["group"], - $options["left_join"])->fetchAll(); - - $shown_dates = array(); - $results = array(); - - $rows = array(); - - foreach ($grab as $row) - foreach ($row as $column => $val) - $rows[$row["id"]][$column][] = $val; - - foreach ($rows as &$row) - foreach ($row as $name => &$column) { - $column = (!in_array($name, $options["ignore_dupes"]) ? - array_unique($column) : - $column); - $column = (count($column) == 1) ? - $column[0] : - $column ; - } - - foreach ($rows as $result) { - if ($options["placeholders"]) { - $results[] = $result; - continue; - } - - $options_for_object["read_from"] = $result; - $result = new $model(null, $options_for_object); - - if (isset($result->created_at)) { - $pinned = (isset($result->pinned) and $result->pinned); - $shown = in_array(when("m-d-Y", $result->created_at), $shown_dates); - - $result->first_of_day = (!$pinned and !$shown and !AJAX); - - if (!$pinned and !$shown) - $shown_dates[] = when("m-d-Y", $result->created_at); - } - - $results[] = $result; - } - - return ($options["placeholders"]) ? array($results, $model_name) : $results ; - } - - /** - * Function: delete - * Deletes a given object. Calls the @delete_(model)@ trigger with the objects ID. - * - * Parameters: - * $model - The model name. - * $id - The ID of the object to delete. - */ - protected static function destroy($model, $id) { - $model = strtolower($model); - if (Trigger::current()->exists("delete_".$model)) - Trigger::current()->call("delete_".$model, new $model($id)); - - SQL::current()->delete(pluralize($model), array("id" => $id)); - } - - /** - * Function: deletable - * Checks if the can delete the post. - */ - public function deletable($user = null) { - if ($this->no_results) - return false; - - $name = strtolower(get_class($this)); - - fallback($user, Visitor::current()); - return $user->group->can("delete_".$name); - } - - /** - * Function: editable - * Checks if the can edit the post. - */ - public function editable($user = null) { - if ($this->no_results) - return false; - - $name = strtolower(get_class($this)); - - fallback($user, Visitor::current()); - return $user->group->can("edit_".$name); - } - - /** - * Function: edit_link - * Outputs an edit link for the model, if the visitor's edit_[model]. - * - * Parameters: - * $text - The text to show for the link. - * $before - If the link can be shown, show this before it. - * $after - If the link can be shown, show this after it. - * $classes - Extra CSS classes for the link, space-delimited. - */ - public function edit_link($text = null, $before = null, $after = null, $classes = "") { - if (!$this->editable()) - return false; - - fallback($text, __("Edit")); - - $name = strtolower(get_class($this)); - - if (@Feathers::$instances[$this->feather]->disable_ajax_edit) - $classes = empty($classes) ? "no_ajax" : $classes." no_ajax" ; - - echo $before.''.$text.''.$after; - } - - /** - * Function: delete_link - * Outputs a delete link for the post, if the delete_[model]. - * - * Parameters: - * $text - The text to show for the link. - * $before - If the link can be shown, show this before it. - * $after - If the link can be shown, show this after it. - * $classes - Extra CSS classes for the link, space-delimited. - */ - public function delete_link($text = null, $before = null, $after = null, $classes = "") { - if (!$this->deletable()) - return false; - - fallback($text, __("Delete")); - - $name = strtolower(get_class($this)); - - echo $before.''.$text.''.$after; - } - } diff --git a/News/includes/class/Modules.php b/News/includes/class/Modules.php deleted file mode 100755 index 7ed2e52..0000000 --- a/News/includes/class/Modules.php +++ /dev/null @@ -1,39 +0,0 @@ -priorities[$name][] = array("priority" => $priority, "function" => array($this, $name)); - } - - /** - * Function: addAlias - * Allows a module to respond to a trigger with multiple functions and custom priorities. - * - * Parameters: - * $name - Name of the trigger to respond to. - * $function - Name of the class function to respond with. - * $priority - Priority of the response. - */ - protected function addAlias($name, $function, $priority = 10) { - Trigger::current()->priorities[$name][] = array("priority" => $priority, "function" => array($this, $function)); - } - } diff --git a/News/includes/class/Paginator.php b/News/includes/class/Paginator.php deleted file mode 100755 index 25ba399..0000000 --- a/News/includes/class/Paginator.php +++ /dev/null @@ -1,229 +0,0 @@ - items be treated as Models? - # In this case, <$array> should be in the form of array(, "ModelName") - public $model; - - # Integer: $total - # Total number of items to paginate. - public $total; - - # Integer: $page - # The current page. - public $page; - - # Integer: $pages - # Total number of pages. - public $pages; - - # Array: $result - # The result of the pagination. - # @paginated@, @paginate@, and @list@ are references to this. - public $result = array(); - - # Array: $names - # An array of the currently-used pagination URL parameters. - static $names = array(); - - /** - * Function: __construct - * Prepares an array for pagination. - * - * Parameters: - * $array - The array to paginate. - * $per_page - Number of items per page. - * $name - The name of the $_GET parameter to use for determining the current page. - * $model - If this is true, each item in $array that gets shown on the page will be - * initialized as a model of whatever is passed as the second argument to $array. - * The first argument of $array is expected to be an array of IDs. - * $page - Page number to start at. - * - * Returns: - * A paginated array of length $per_page or smaller. - */ - public function __construct($array, $per_page = 5, $name = "page", $model = null, $page = null) { - self::$names[] = $name; - - $this->array = (array) $array; - - $this->per_page = $per_page; - $this->name = $name; - $this->model = fallback($model, (count($this->array) == 2 and is_array($this->array[0]) and is_string($this->array[1]) and class_exists($this->array[1]))); - - if ($model) - list($this->array, $model_name) = $this->array; - - $this->total = count($this->array); - $this->page = oneof($page, @$_GET[$name], 1); - $this->pages = ceil($this->total / $this->per_page); - - $offset = ($this->page - 1) * $this->per_page; - - $this->result = array(); - - if ($model) { - for ($i = $offset; $i < ($offset + $this->per_page); $i++) - if (isset($this->array[$i])) - $this->result[] = new $model_name(null, array("read_from" => $this->array[$i])); - } else - $this->result = array_slice($this->array, $offset, $this->per_page); - - $shown_dates = array(); - if ($model) - foreach ($this->result as &$result) - if (isset($result->created_at)) { - $pinned = (isset($result->pinned) and $result->pinned); - $shown = in_array(when("m-d-Y", $result->created_at), $shown_dates); - - $result->first_of_day = (!$pinned and !$shown and !AJAX); - - if (!$pinned and !$shown) - $shown_dates[] = when("m-d-Y", $result->created_at); - } - - $this->paginated = $this->paginate = $this->list =& $this->result; - } - - /** - * Function: next - * Returns the next pagination sequence. - */ - public function next() { - return new self($this->array, $this->per_page, $this->name, $this->model, $this->page + 1); - } - - /** - * Function: prev - * Returns the next pagination sequence. - */ - public function prev() { - return new self($this->array, $this->per_page, $this->name, $this->model, $this->page - 1); - } - - /** - * Function: next_page - * Checks whether or not it makes sense to show the Next Page link. - */ - public function next_page() { - return ($this->page < $this->pages and $this->pages != 1 and $this->pages != 0); - } - - /** - * Function: prev_page - * Checks whether or not it makes sense to show the Previous Page link. - */ - public function prev_page() { - return ($this->page != 1 and $this->page <= $this->pages); - } - - /** - * Function: next_link - * Outputs a link to the next page. - * - * Parameters: - * $text - The text for the link. - * $class - The CSS class for the link. - * $page - Page number to link to. - */ - public function next_link($text = null, $class = "next_page", $page = null) { - if (!$this->next_page()) - return; - - fallback($text, __("Next →")); - echo ''. - $text. - ''; - } - - /** - * Function: prev_link - * Outputs a link to the previous page. - * - * Parameters: - * $text - The text for the link. - * $class - The CSS class for the link. - * $page - Page number to link to. - */ - public function prev_link($text = null, $class = "prev_page", $page = null) { - if (!$this->prev_page()) - return; - - fallback($text, __("← Previous")); - echo ''. - $text. - ''; - } - - /** - * Function: next_page_url - * Returns the URL to the next page. - * - * Parameters: - * $page - Page number to link to. - */ - public function next_page_url($page = null) { - $config = Config::current(); - - $request = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; - - # Only used for adding to the end of the URL and clean URLs is off. - $mark = (substr_count($request, "?")) ? "&" : "?" ; - - fallback($page, $this->page + 1); - - # No page is set, add it to the end. - if (!isset($_GET[$this->name])) - return ($config->clean_urls and !ADMIN) ? - rtrim($request, "/")."/".$this->name."/".$page : - $request.$mark.$this->name."=".$page ; - - return ($config->clean_urls and !ADMIN) ? - preg_replace("/(\/{$this->name}\/([0-9]+)|$)/", "/".$this->name."/".$page, $request, 1) : - preg_replace("/((\?|&){$this->name}=([0-9]+)|$)/", "\\2".$this->name."=".$page, $request, 1) ; - } - - /** - * Function: prev_page_url - * Returns the URL to the previous page. - * - * Parameters: - * $page - Page number to link to. - */ - public function prev_page_url($page = null) { - $config = Config::current(); - - $request = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; - - # Only used for adding to the end of the URL and clean URLs is off. - $mark = (substr_count($request, "?")) ? "&" : "?" ; - - fallback($page, $this->page - 1); - - # No page is set, add it to the end. - if (!isset($_GET[$this->name])) - return ($config->clean_urls and !ADMIN) ? - rtrim($request, "/")."/".$this->name."/".$page : - $request.$mark.$this->name."=".$page ; - - return ($config->clean_urls and !ADMIN) ? - preg_replace("/(\/{$this->name}\/([0-9]+)|$)/", "/".$this->name."/".$page, $request, 1) : - preg_replace("/((\?|&){$this->name}=([0-9]+)|$)/", "\\2".$this->name."=".$page, $request, 1) ; - } - } diff --git a/News/includes/class/Query.php b/News/includes/class/Query.php deleted file mode 100644 index 1eae6bd..0000000 --- a/News/includes/class/Query.php +++ /dev/null @@ -1,236 +0,0 @@ -. - */ - class Query { - # Variable: $query - # Holds the current query. - public $query; - - /** - * Function: __construct - * Creates a query based on the . - * - * Parameters: - * $sql - instance. - * $query - Query to execute. - * $params - An associative array of parameters used in the query. - * $throw_exceptions - Throw exceptions on error? - */ - public function __construct($sql, $query, $params = array(), $throw_exceptions = false) { - if (DEBUG) - global $time_start; - - $this->sql = $sql; - - # Don't count config setting queries. - $count = !preg_match("/^SET /", strtoupper($query)); - - if ($count) - ++$this->sql->queries; - - $this->db =& $this->sql->db; - - $this->params = $params; - $this->throw_exceptions = $throw_exceptions; - $this->queryString = $query; - - if ($count and defined('DEBUG') and DEBUG) { - $trace = debug_backtrace(); - $target = $trace[$index = 0]; - - # Getting a traceback from these files doesn't help much. - while (match(array("/SQL\.php/", "/Model\.php/", "/\/model\//"), $target["file"])) - if (isset($trace[$index + 1]["file"])) - $target = $trace[$index++]; - else - break; - - $logQuery = $query; - foreach ($params as $name => $val) - $logQuery = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/", str_replace("\\", "\\\\", $this->sql->escape($val))."\\1", $logQuery); - - $this->sql->debug[] = array("number" => $this->sql->queries, - "file" => str_replace(MAIN_DIR."/", "", $target["file"]), - "line" => $target["line"], - "query" => $logQuery, - "time" => timer_stop()); - } - - switch($this->sql->method) { - case "pdo": - try { - $this->query = $this->db->prepare($query); - $result = $this->query->execute($params); - $this->query->setFetchMode(PDO::FETCH_ASSOC); - - $this->queryString = $query; - foreach ($params as $name => $val) - $this->queryString = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/", - str_replace(array("\\", "\$"), - array("\\\\", "\\\$"), - $this->sql->escape($val))."\\1", - $this->queryString); - - if (!$result) - throw new PDOException; - } catch (PDOException $error) { - if (!empty($error->errorInfo[1]) and $error->errorInfo[1] == 17) - return new self($sql, $query, $params, $throw_exceptions); - - return $this->handle($error); - } - break; - case "mysqli": - foreach ($params as $name => $val) - $query = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/", - str_replace(array("\\", "\$"), - array("\\\\", "\\\$"), - $this->sql->escape($val))."\\1", - $query); - - $this->queryString = $query; - - try { - if (!$this->query = $this->db->query($query)) - throw new Exception($this->db->error); - } catch (Exception $error) { - return $this->handle($error); - } - break; - case "mysql": - foreach ($params as $name => $val) - $query = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/", - str_replace(array("\\", "\$"), - array("\\\\", "\\\$"), - $this->sql->escape($val))."\\1", - $query); - - $this->queryString = $query; - - try { - if (!$this->query = @mysql_query($query)) - throw new Exception(mysql_error()); - } catch (Exception $error) { - return $this->handle($error); - } - - break; - } - } - - /** - * Function: fetchColumn - * Fetches a column of the current row. - * - * Parameters: - * $column - The offset of the column to grab. Default 0. - */ - public function fetchColumn($column = 0) { - switch($this->sql->method) { - case "pdo": - return $this->query->fetchColumn($column); - case "mysqli": - $result = $this->query->fetch_array(); - return $result[$column]; - case "mysql": - $result = mysql_fetch_array($this->query); - return $result[$column]; - } - } - - /** - * Function: fetch - * Returns the current row as an array. - */ - public function fetch() { - switch($this->sql->method) { - case "pdo": - return $this->query->fetch(); - case "mysqli": - return $this->query->fetch_array(); - case "mysql": - return mysql_fetch_array($this->query); - } - } - - /** - * Function: fetchObject - * Returns the current row as an object. - */ - public function fetchObject() { - switch($this->sql->method) { - case "pdo": - return $this->query->fetchObject(); - case "mysqli": - return $this->query->fetch_object(); - case "mysql": - return mysql_fetch_object($this->query); - } - } - - /** - * Function: fetchAll - * Returns an array of every result. - */ - public function fetchAll($style = null) { - switch($this->sql->method) { - case "pdo": - return $this->query->fetchAll($style); - case "mysqli": - $results = array(); - - while ($row = $this->query->fetch_assoc()) - $results[] = $row; - - return $results; - case "mysql": - $results = array(); - - while ($row = mysql_fetch_assoc($this->query)) - $results[] = $row; - - return $results; - } - } - - /** - * Function: grab - * Grabs all of the given column out of the full result of a query. - * - * Parameters: - * $column - Name of the column to grab. - * - * Returns: - * An array of all of the values of that column in the result. - */ - public function grab($column) { - $all = $this->fetchAll(); - - $result = array(); - foreach ($all as $row) - $result[] = $row[$column]; - - return $result; - } - - /** - * Function: handle - * Handles exceptions thrown by failed queries. - */ - public function handle($error) { - $this->sql->error = $error; - - if (UPGRADING or $this->sql->silence_errors) return false; - - $message = $error->getMessage(); - - $message.= "\n\n
    ".print_r($this->queryString, true)."\n\n
    ".print_r($this->params, true)."
    \n\n
    ".$error->getTraceAsString()."
    "; - - if (XML_RPC or $this->throw_exceptions) - throw new Exception($message); - - error(__("Database Error"), $message); - } - } diff --git a/News/includes/class/QueryBuilder.php b/News/includes/class/QueryBuilder.php deleted file mode 100644 index 4da0315..0000000 --- a/News/includes/class/QueryBuilder.php +++ /dev/null @@ -1,449 +0,0 @@ - $val) - $params[":".str_replace(array("(", ")", "."), "_", $key)] = $val; - - return "INSERT INTO __$table\n". - self::build_insert_header($data)."\n". - "VALUES\n". - "(".implode(", ", array_keys($params)).")\n"; - } - - /** - * Function: build_update - * Creates a full update query. - * - * Parameters: - * $table - Table to update. - * $conds - Conditions to update rows by. - * $data - Data to update. - * &$params - An associative array of parameters used in the query. - * - * Returns: - * An @UPDATE@ query string. - */ - public static function build_update($table, $conds, $data, &$params = array()) { - return "UPDATE __$table\n". - "SET ".self::build_update_values($data, $params)."\n". - ($conds ? "WHERE ".self::build_where($conds, $table, $params) : ""); - } - - /** - * Function: build_delete - * Creates a full delete query. - * - * Parameters: - * $table - Table to delete from. - * $conds - Conditions to delete by. - * &$params - An associative array of parameters used in the query. - * - * Returns: - * A @DELETE@ query string. - */ - public static function build_delete($table, $conds, &$params = array()) { - return "DELETE FROM __$table\n". - ($conds ? "WHERE ".self::build_where($conds, $table, $params) : ""); - } - - /** - * Function: build_update_values - * Creates an update data part. - * - * Parameters: - * $data - Data to update. - * &$params - An associative array of parameters used in the query. - */ - public static function build_update_values($data, &$params = array()) { - $set = self::build_conditions($data, $params, null, true); - return implode(",\n ", $set); - } - - /** - * Function: build_insert_header - * Creates an insert header. - * - * Parameters: - * $data - Data to insert. - */ - public static function build_insert_header($data) { - $set = array(); - - foreach (array_keys($data) as $field) - array_push($set, self::safecol($field)); - - return "(".implode(", ", $set).")"; - } - - /** - * Function: build_limits - * Creates the LIMIT part of a query. - * - * Parameters: - * $offset - Offset of the result. - * $limit - Limit of the result. - */ - public static function build_limits($offset, $limit) { - if ($limit === null) - return ""; - - if ($offset !== null) - return "LIMIT ".$offset.", ".$limit; - - return "LIMIT ".$limit; - } - - /** - * Function: build_from - * Creates a FROM header for select queries. - * - * Parameters: - * $tables - Tables to select from. - */ - public static function build_from($tables) { - if (!is_array($tables)) - $tables = array($tables); - - foreach ($tables as &$table) - if (substr($table, 0, 2) != "__") - $table = "__".$table; - - return implode(",\n ", $tables); - } - - /** - * Function: build_count - * Creates a SELECT COUNT(1) query. - * - * Parameters: - * $tables - Tables to tablefy with. - * $conds - Conditions to select by. - * &$params - An associative array of parameters used in the query. - */ - public static function build_count($tables, $conds, &$params = array()) { - return "SELECT COUNT(1) AS count\n". - "FROM ".self::build_from($tables)."\n". - ($conds ? "WHERE ".self::build_where($conds, $tables, $params) : ""); - } - - /** - * Function: build_select_header - * Creates a SELECT fields header. - * - * Parameters: - * $fields - Columns to select. - * $tables - Tables to tablefy with. - */ - public static function build_select_header($fields, $tables = null) { - if (!is_array($fields)) - $fields = array($fields); - - $tables = (array) $tables; - - foreach ($fields as &$field) { - self::tablefy($field, $tables); - $field = self::safecol($field); - } - - return implode(",\n ", $fields); - } - - /** - * Function: build_where - * Creates a WHERE query. - */ - public static function build_where($conds, $tables = null, &$params = array()) { - $conds = (array) $conds; - $tables = (array) $tables; - - $conditions = self::build_conditions($conds, $params, $tables); - - return (empty($conditions)) ? "" : "(".implode(")\n AND (", array_filter($conditions)).")"; - } - - /** - * Function: build_group - * Creates a GROUP BY argument. - * - * Parameters: - * $order - Columns to group by. - * $tables - Tables to tablefy with. - */ - public static function build_group($by, $tables = null) { - $by = (array) $by; - $tables = (array) $tables; - - foreach ($by as &$column) { - self::tablefy($column, $tables); - $column = self::safecol($column); - } - - return implode(",\n ", array_unique(array_filter($by))); - } - - /** - * Function: build_order - * Creates an ORDER BY argument. - * - * Parameters: - * $order - Columns to order by. - * $tables - Tables to tablefy with. - */ - public static function build_order($order, $tables = null) { - $tables = (array) $tables; - - if (!is_array($order)) - $order = comma_sep($order); - - foreach ($order as &$by) { - self::tablefy($by, $tables); - $by = self::safecol($by); - } - - return implode(",\n ", $order); - } - - /** - * Function: build_list - * Returns ('one', 'two', '', 1, 0) from array("one", "two", null, true, false) - */ - public static function build_list($vals, $params = array()) { - $return = array(); - - foreach ($vals as $val) { - if (is_object($val)) # Useful catch, e.g. empty SimpleXML objects. - $val = ""; - - $return[] = (isset($params[$val])) ? $val : SQL::current()->escape($val) ; - } - - return "(".join(", ", $return).")"; - } - - /** - * Function: safecol - * Wraps a column in proper escaping if it is a SQL keyword. - * - * Doesn't check every keyword, just the common/sensible ones. - * - * ...Okay, it only does two. "order" and "group". - * - * Parameters: - * $name - Name of the column. - */ - public static function safecol($name) { - return preg_replace("/(([^a-zA-Z0-9_]|^)(order|group)([^a-zA-Z0-9_]| -$))/i", - (SQL::current()->adapter == "mysql") ? "\\2`\\3` -\\4" : '\\2"\\3"\\4', - $name); - } - - /** - * Function: build_conditions - * Builds an associative array of SQL values into PDO-esque paramized query strings. - * - * Parameters: - * $conds - Conditions. - * &$params - Parameters array to fill. - * $tables - If specified, conditions will be tablefied with these tables. - * $insert - Is this an insert/update query? - */ - public static function build_conditions($conds, &$params, $tables = null, $insert = false) { - $conditions = array(); - - foreach ($conds as $key => $val) { - if (is_int($key)) # Full expression - $cond = $val; - else { # Key => Val expression - if (is_string($val) and strlen($val) and $val[0] == ":") - $cond = self::safecol($key)." = ".$val; - else { - if (is_bool($val)) - $val = (int) $val; - - if (substr($key, -4) == " not") { # Negation - $key = self::safecol(substr($key, 0, -4)); - $param = str_replace(array("(", ")", "."), "_", $key); - if (is_array($val)) - $cond = $key." NOT IN ".self::build_list($val, $params); - elseif ($val === null) - $cond = $key." IS NOT NULL"; - else { - $cond = $key." != :".$param; - $params[":".$param] = $val; - } - } elseif (substr($key, -5) == " like" and is_array($val)) { # multiple LIKE - $key = self::safecol(substr($key, 0, -5)); - - $likes = array(); - foreach ($val as $index => $match) { - $param = str_replace(array("(", ")", "."), "_", $key)."_".$index; - $likes[] = $key." LIKE :".$param; - $params[":".$param] = $match; - } - - $cond = "(".implode(" OR ", $likes).")"; - } elseif (substr($key, -9) == " like all" and is_array($val)) { # multiple LIKE - $key = self::safecol(substr($key, 0, -9)); - - $likes = array(); - foreach ($val as $index => $match) { - $param = str_replace(array("(", ")", "."), "_", $key)."_".$index; - $likes[] = $key." LIKE :".$param; - $params[":".$param] = $match; - } - - $cond = "(".implode(" AND ", $likes).")"; - } elseif (substr($key, -9) == " not like" and is_array($val)) { # multiple NOT LIKE - $key = self::safecol(substr($key, 0, -9)); - - $likes = array(); - foreach ($val as $index => $match) { - $param = str_replace(array("(", ")", "."), "_", $key)."_".$index; - $likes[] = $key." NOT LIKE :".$param; - $params[":".$param] = $match; - } - - $cond = "(".implode(" AND ", $likes).")"; - } elseif (substr($key, -5) == " like") { # LIKE - $key = self::safecol(substr($key, 0, -5)); - $param = str_replace(array("(", ")", "."), "_", $key); - $cond = $key." LIKE :".$param; - $params[":".$param] = $val; - } elseif (substr($key, -9) == " not like") { # NOT LIKE - $key = self::safecol(substr($key, 0, -9)); - $param = str_replace(array("(", ")", "."), "_", $key); - $cond = $key." NOT LIKE :".$param; - $params[":".$param] = $val; - } elseif (substr_count($key, " ")) { # Custom operation, e.g. array("foo >" => $bar) - list($param,) = explode(" ", $key); - $param = str_replace(array("(", ")", "."), "_", $param); - $cond = self::safecol($key)." :".$param; - $params[":".$param] = $val; - } else { # Equation - if (is_array($val)) - $cond = self::safecol($key)." IN ".self::build_list($val, $params); - elseif ($val === null and $insert) - $cond = self::safecol($key)." = ''"; - elseif ($val === null) - $cond = self::safecol($key)." IS NULL"; - else { - $param = str_replace(array("(", ")", "."), "_", $key); - $cond = self::safecol($key)." = :".$param; - $params[":".$param] = $val; - } - } - } - } - - if ($tables) - self::tablefy($cond, $tables); - - $conditions[] = $cond; - } - - return $conditions; - } - - /** - * Function: tablefy - * Automatically prepends tables and table prefixes to a field if it doesn't already have them. - * - * Parameters: - * &$field - The field to "tablefy". - * $tables - An array of tables. The first one will be used for prepending. - */ - public static function tablefy(&$field, $tables) { - if (!preg_match_all("/(\(|[\s]+|^)(?!__)([a-z0-9_\.\*]+)(\)|[\s]+|$)/", $field, $matches)) - return $field = str_replace("`", "", $field); # Method for bypassing the prefixer. - - foreach ($matches[0] as $index => $full) { - $before = $matches[1][$index]; - $name = $matches[2][$index]; - $after = $matches[3][$index]; - - if (is_numeric($name)) - continue; - - # Does it not already have a table specified? - if (!substr_count($full, ".")) { - # Don't replace things that are already either prefixed or paramized. - $field = preg_replace("/([^\.:'\"_]|^)".preg_quote($full, "/")."/", - "\\1".$before."__".$tables[0].".".$name.$after, - $field, - 1); - } else { - # Okay, it does, but is the table prefixed? - if (substr($full, 0, 2) != "__") { - # Don't replace things that are already either prefixed or paramized. - $field = preg_replace("/([^\.:'\"_]|^)".preg_quote($full, "/")."/", - "\\1".$before."__".$name.$after, - $field, - 1); - } - } - } - - $field = preg_replace("/AS ([^ ]+)\./i", "AS ", $field); - } - } - - diff --git a/News/includes/class/Route.php b/News/includes/class/Route.php deleted file mode 100755 index 386558f..0000000 --- a/News/includes/class/Route.php +++ /dev/null @@ -1,235 +0,0 @@ - call a successful route? - public $success = false; - - # Variable: $controller - # The Route's Controller. - public $controller; - - /** - * Function: __construct - * Parse the URL and to determine what to do. - * - * Parameters: - * $controller - The controller to use. - */ - private function __construct($controller) { - $this->controller = $controller; - - $config = Config::current(); - - if (substr_count($_SERVER['REQUEST_URI'], "..") > 0 ) - exit("GTFO."); - elseif (isset($_GET['action']) and preg_match("/[^(\w+)]/", $_GET['action'])) - exit("Nope!"); - - $this->action =& $_GET['action']; - - if (isset($_GET['feed'])) - $this->feed = true; - - # Parse the current URL and extract information. - $parse = parse_url($config->url); - fallback($parse["path"], "/"); - - if (isset($controller->base)) - $parse["path"] = trim($parse["path"], "/")."/".trim($controller->base, "/")."/"; - - $this->safe_path = str_replace("/", "\\/", $parse["path"]); - $this->request = $parse["path"] == "/" ? - $_SERVER['REQUEST_URI'] : - preg_replace("/{$this->safe_path}?/", "", $_SERVER['REQUEST_URI'], 1) ; - $this->arg = array_map("urldecode", explode("/", trim($this->request, "/"))); - - if (substr_count($this->arg[0], "?") > 0 and !preg_match("/\?\w+/", $this->arg[0])) - exit("No-Go!"); - - if (method_exists($controller, "parse")) - $controller->parse($this); - - Trigger::current()->call("parse_url", $this); - - $this->try[] = isset($this->action) ? - oneof($this->action, "index") : - (!substr_count($this->arg[0], "?") ? - oneof(@$this->arg[0], "index") : - "index") ; - - # Guess the action initially. - # This is only required because of the view_site permission; - # it has to know if they're viewing /login, in which case - # it should allow the page to display. - fallback($this->action, end($this->try)); - } - - /** - * Function: init - * Attempt Controller actions until one of them doesn't return false. - * - * This will also call the @[controllername]_xxxxx@ and @route_xxxxx@ triggers. - */ - public function init() { - $trigger = Trigger::current(); - - $trigger->call("route_init", $this); - - $try = $this->try; - - if (isset($this->action)) - array_unshift($try, $this->action); - - $count = 0; - foreach ($try as $key => $val) { - if (is_numeric($key)) - list($method, $args) = array($val, array()); - else - list($method, $args) = array($key, $val); - - $this->action = $method; - - $name = strtolower(str_replace("Controller", "", get_class($this->controller))); - if ($trigger->exists($name."_".$method) or $trigger->exists("route_".$method)) - $call = $trigger->call(array($name."_".$method, "route_".$method), $this->controller); - else - $call = false; - - if ($call !== true and method_exists($this->controller, $method)) - $response = call_user_func_array(array($this->controller, $method), $args); - else - $response = false; - - if ($response !== false or $call !== false) { - $this->success = true; - break; - } - - if (++$count == count($try) and isset($this->controller->fallback) and method_exists($this->controller, "display")) - call_user_func_array(array($this->controller, "display"), $this->controller->fallback); - } - - if ($this->action != "login" and $this->success) - $_SESSION['redirect_to'] = self_url(); - - $trigger->call("route_done", $this); - - return true; - } - - /** - * Function: url - * Attempts to change the specified clean URL to a dirty URL if clean URLs is disabled. - * Use this for linking to things. The applicable URL conversions are passed through the - * parse_urls trigger. - * - * Parameters: - * $url - The clean URL. - * $use_chyrp_url - Use @Config.chyrp_url@ instead of @Config.url@, when the @$url@ begins with "/"? - * - * Returns: - * A clean or dirty URL, depending on @Config.clean_urls@. - */ - public function url($url, $controller = null) { - $config = Config::current(); - - if ($url[0] == "/") - return (ADMIN ? - $config->chyrp_url.$url : - $config->url.$url); - else - $url = substr($url, -1) == "/" ? $url : $url."/" ; - - fallback($controller, $this->controller); - - $base = !empty($controller->base) ? $config->url."/".$controller->base : $config->url ; - - if ($config->clean_urls) { # If their post URL doesn't have a trailing slash, remove it from these as well. - if (substr($url, 0, 5) == "page/") # Different URL for viewing a page - $url = substr($url, 5); - - return (substr($config->post_url, -1) == "/" or $url == "search/") ? - $base."/".$url : - $base."/".rtrim($url, "/") ; - } - - $urls = fallback($controller->urls, array()); - Trigger::current()->filter($urls, "parse_urls"); - - foreach (array_diff_assoc($urls, $controller->urls) as $key => $value) - $urls[substr($key, 0, -1).preg_quote("feed/", $key[0]).$key[0]] = "/".$value."&feed"; - - $urls["|/([^/]+)/$|"] = "/?action=$1"; - - return $base.fix(preg_replace(array_keys($urls), array_values($urls), "/".$url, 1)); - } - - /** - * Function: add - * Adds a route to Chyrp. Only needed for actions that have more than one parameter. - * For example, for /tags/ you won't need to do this, but you will for /tag/tag-name/. - * - * Parameters: - * $path - The path to add. Wrap variables with parentheses, e.g. "tag/(name)/". - * $action - The action the path points to. - * - * See Also: - * - */ - public function add($path, $action) { - $config = Config::current(); - - $new_routes = $config->routes; - $new_routes[$path] = $action; - - $config->set("routes", $new_routes); - } - - /** - * Function: remove - * Removes a route added by . - * - * Parameters: - * $path - The path to remove. - * - * See Also: - * - */ - public function remove($path) { - $config = Config::current(); - - unset($config->routes[$path]); - - $config->set("routes", $config->routes); - } - - /** - * Function: current - * Returns a singleton reference to the current class. - */ - public static function & current($controller = null) { - static $instance = null; - - if (!isset($controller) and empty($instance)) - error(__("Error"), __("Route was initiated without a Controller."), debug_backtrace()); - - return $instance = (empty($instance)) ? new self($controller) : $instance ; - } - } - diff --git a/News/includes/class/SQL.php b/News/includes/class/SQL.php deleted file mode 100755 index 52b42f3..0000000 --- a/News/includes/class/SQL.php +++ /dev/null @@ -1,473 +0,0 @@ - - require_once INCLUDES_DIR."/class/Query.php"; - - # File: QueryBuilder - # See Also: - # - require_once INCLUDES_DIR."/class/QueryBuilder.php"; - - class SQL { - # Array: $debug - # Holds debug information for SQL queries. - public $debug = array(); - - # Integer: $queries - # Number of queries it takes to load the page. - public $queries = 0; - - # Variable: $db - # Holds the currently running database. - public $db; - - # Variable: $error - # Holds an error message from the last attempted query. - public $error = ""; - - # Boolean: $silence_errors - # Ignore errors? - public $silence_errors = false; - - /** - * Function: __construct - * The class constructor is private so there is only one connection. - * - * Parameters: - * $settings - Settings to load instead of the config. - */ - private function __construct($settings = array()) { - if (!UPGRADING and !INSTALLING and !isset(Config::current()->sql)) - error(__("Error"), __("Database configuration is not set. Please run the upgrader.")); - - $database = !UPGRADING ? - oneof(@Config::current()->sql, array()) : - Config::get("sql") ; - - if (is_array($settings)) - fallback($database, $settings); - elseif ($settings === true) - $this->silence_errors = true; - - if (!empty($database)) - foreach ($database as $setting => $value) - $this->$setting = $value; - - $this->connected = false; - - # We really don't need PDO anymore, since we have the two we supported with it hardcoded (kinda). - # Keeping this here for when/if we decide to add support for more database engines, like Postgres and MSSQL. - # if (class_exists("PDO") and (in_array("mysql", PDO::getAvailableDrivers()) or in_array("sqlite", PDO::getAvailableDrivers()))) - # return $this->method = "pdo"; - - if (isset($this->adapter)) { - if ($this->adapter == "mysql" and class_exists("MySQLi")) - $this->method = "mysqli"; - elseif ($this->adapter == "mysql" and function_exists("mysql_connect")) - $this->method = "mysql"; - elseif (class_exists("PDO") and - ($this->adapter == "sqlite" and in_array("sqlite", PDO::getAvailableDrivers()) or - $this->adapter == "pgsql" and in_array("pgsql", PDO::getAvailableDrivers()))) - $this->method = "pdo"; - } else - if (class_exists("MySQLi")) - $this->method = "mysqli"; - elseif (function_exists("mysql_connect")) - $this->method = "mysql"; - elseif (class_exists("PDO") and in_array("mysql", PDO::getAvailableDrivers())) - $this->method = "pdo"; - } - - /** - * Function: set - * Sets a variable's value. - * - * Parameters: - * $setting - The setting name. - * $value - The new value. Can be boolean, numeric, an array, a string, etc. - * $overwrite - If the setting exists and is the same value, should it be overwritten? - */ - public function set($setting, $value, $overwrite = true) { - if (isset($this->$setting) and $this->$setting == $value and !$overwrite and !UPGRADING) - return false; - - if (!UPGRADING) - $config = Config::current(); - - $database = (!UPGRADING) ? fallback($config->sql, array()) : Config::get("sql") ; - - # Add the setting - $database[$setting] = $this->$setting = $value; - - return (!UPGRADING) ? $config->set("sql", $database) : Config::set("sql", $database) ; - } - - /** - * Function: connect - * Connects to the SQL database. - * - * Parameters: - * $checking - Return a boolean of whether or not it could connect, instead of showing an error. - */ - public function connect($checking = false) { - if ($this->connected) - return true; - - if (!isset($this->database)) - self::__construct(); - - if (UPGRADING) - $checking = true; - - switch($this->method) { - case "pdo": - try { - if (empty($this->database)) - throw new PDOException("No database specified."); - - if ($this->adapter == "sqlite") { - $this->db = new PDO("sqlite:".$this->database, null, null, array(PDO::ATTR_PERSISTENT => true)); - $this->db->sqliteCreateFunction("YEAR", array($this, "year_from_datetime"), 1); - $this->db->sqliteCreateFunction("MONTH", array($this, "month_from_datetime"), 1); - $this->db->sqliteCreateFunction("DAY", array($this, "day_from_datetime"), 1); - $this->db->sqliteCreateFunction("HOUR", array($this, "hour_from_datetime"), 1); - $this->db->sqliteCreateFunction("MINUTE", array($this, "minute_from_datetime"), 1); - $this->db->sqliteCreateFunction("SECOND", array($this, "second_from_datetime"), 1); - } else - $this->db = new PDO($this->adapter.":host=".$this->host.";".((isset($this->port)) ? "port=".$this->port.";" : "")."dbname=".$this->database, - $this->username, - $this->password, - array(PDO::ATTR_PERSISTENT => true)); - - $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } catch (PDOException $error) { - $this->error = $error->getMessage(); - return ($checking) ? false : error(__("Database Error"), $this->error) ; - } - break; - case "mysqli": - $this->db = @new MySQLi($this->host, $this->username, $this->password, $this->database); - $this->error = mysqli_connect_error(); - - if (mysqli_connect_errno()) - return ($checking) ? false : error(__("Database Error"), $this->error) ; - - break; - case "mysql": - $this->db = @mysql_connect($this->host, $this->username, $this->password); - $this->error = mysql_error(); - - if (!$this->db or !@mysql_select_db($this->database)) - return ($checking) ? false : error(__("Database Error"), $this->error) ; - - break; - } - - if ($this->adapter == "mysql") - new Query($this, "SET NAMES 'utf8'"); # Note: This doesn't increase the query debug/count. - - return $this->connected = true; - } - - /** - * Function: query - * Executes a query and increases $queries>. - * If the query results in an error, it will die and show the error. - * - * Parameters: - * $query - Query to execute. - * $params - An associative array of parameters used in the query. - * $throw_exceptions - Should an exception be thrown if the query fails? - */ - public function query($query, $params = array(), $throw_exceptions = false) { - if (!$this->connected) - return false; - - # Ensure that every param in $params exists in the query. - # If it doesn't, remove it from $params. - foreach ($params as $name => $val) - if (!strpos($query, $name)) - unset($params[$name]); - - $query = str_replace("__", $this->prefix, $query); - - if ($this->adapter == "sqlite") - $query = str_ireplace(" DEFAULT CHARSET=utf8", "", str_ireplace("AUTO_INCREMENT", "AUTOINCREMENT", $query)); - - if ($this->adapter == "pgsql") - $query = str_ireplace(array("CREATE TABLE IF NOT EXISTS", - "INTEGER PRIMARY KEY AUTO_INCREMENT", - ") DEFAULT CHARSET=utf8", - "TINYINT", - "DATETIME", - "DEFAULT '0000-00-00 00:00:00'", - "LONGTEXT", - "REPLACE INTO"), - array("CREATE TABLE", - "SERIAL PRIMARY KEY", - ")", - "SMALLINT", - "TIMESTAMP", - "", - "TEXT", - "INSERT INTO"), - $query); - - $query = new Query($this, $query, $params, $throw_exceptions); - - return (!$query->query and UPGRADING) ? false : $query ; - } - - /** - * Function: count - * Performs a counting query and returns the number of matching rows. - * - * Parameters: - * $tables - An array (or string) of tables to count results on. - * $conds - An array (or string) of conditions to match. - * $params - An associative array of parameters used in the query. - * $throw_exceptions - Should exceptions be thrown on error? - */ - public function count($tables, $conds = null, $params = array(), $throw_exceptions = false) { - $query = $this->query(QueryBuilder::build_count($tables, $conds, $params), $params, $throw_exceptions); - return ($query->query) ? $query->fetchColumn() : false ; - } - - /** - * Function: select - * Performs a SELECT with given criteria and returns the query result object. - * - * Parameters: - * $tables - An array (or string) of tables to grab results from. - * $fields - Fields to select. - * $conds - An array (or string) of conditions to match. - * $order - ORDER BY statement. Can be an array. - * $params - An associative array of parameters used in the query. - * $limit - Limit for results. - * $offset - Offset for the select statement. - * $group - GROUP BY statement. Can be an array. - * $left_join - An array of additional LEFT JOINs. - * $throw_exceptions - Should exceptions be thrown on error? - */ - public function select($tables, $fields = "*", $conds = null, $order = null, $params = array(), $limit = null, $offset = null, $group = null, $left_join = array(), $throw_exceptions = false) { - return $this->query(QueryBuilder::build_select($tables, $fields, $conds, $order, $limit, $offset, $group, $left_join, $params), $params, $throw_exceptions); - } - - /** - * Function: insert - * Performs an INSERT with given data. - * - * Parameters: - * $table - Table to insert to. - * $data - An associative array of data to insert. - * $params - An associative array of parameters used in the query. - * $throw_exceptions - Should exceptions be thrown on error? - */ - public function insert($table, $data, $params = array(), $throw_exceptions = false) { - return $this->query(QueryBuilder::build_insert($table, $data, $params), $params, $throw_exceptions); - } - - /** - * Function: replace - * Performs either an INSERT or an UPDATE depending on - * whether a row exists with the specified keys matching - * their values in the data. - * - * Parameters: - * $table - Table to update or insert into. - * $keys - Columns to match on. - * $data - Data for the insert and value matches for the keys. - * $params - An associative array of parameters to be used in the query. - * $throw_exceptions - Should exceptions be thrown on error? - */ - public function replace($table, $keys, $data, $params = array(), $throw_exceptions = false) { - $match = array(); - foreach ((array) $keys as $key) - $match[$key] = $data[$key]; - - if ($this->count($table, $match, $params)) - $this->update($table, $match, $data, $params, $throw_exceptions); - else - $this->insert($table, $data, $params, $throw_exceptions); - } - - /** - * Function: update - * Performs an UDATE with given criteria and data. - * - * Parameters: - * $table - Table to update. - * $conds - Rows to update. - * $data - An associative array of data to update. - * $params - An associative array of parameters used in the query. - * $throw_exceptions - Should exceptions be thrown on error? - */ - public function update($table, $conds, $data, $params = array(), $throw_exceptions = false) { - return $this->query(QueryBuilder::build_update($table, $conds, $data, $params), $params, $throw_exceptions); - } - - /** - * Function: delete - * Performs a DELETE with given criteria. - * - * Parameters: - * $table - Table to delete from. - * $conds - Rows to delete.. - * $params - An associative array of parameters used in the query. - * $throw_exceptions - Should exceptions be thrown on error? - */ - public function delete($table, $conds, $params = array(), $throw_exceptions = false) { - return $this->query(QueryBuilder::build_delete($table, $conds, $params), $params, $throw_exceptions); - } - - /** - * Function: latest - * Returns the last inserted sequential value. - * Both function arguments are only relevant for PostgreSQL. - * - * Parameters: - * $table - Table to get the latest value from. - * $seq - Name of the sequence. - */ - public function latest($table, $seq = "id_seq") { - if (!isset($this->db)) - $this->connect(); - - switch($this->method) { - case "pdo": - return $this->db->lastInsertId($this->prefix.$table."_".$seq); - break; - case "mysqli": - return $this->db->insert_id; - break; - case "mysql": - return @mysql_insert_id(); - break; - } - } - - /** - * Function: escape - * Escapes a string, escaping things like $1 and C:\foo\bar so that they don't get borked by the preg_replace. - * - * This also handles calling the SQL connection method's "escape_string" functions. - * - * Parameters: - * $string - String to escape. - * $quotes - Auto-wrap the string in quotes (@'@)? - */ - public function escape($string, $quotes = true) { - if (!isset($this->db)) - $this->connect(); - - switch($this->method) { - case "pdo": - $string = ltrim(rtrim($this->db->quote($string), "'"), "'"); - break; - case "mysqli": - $string = $this->db->escape_string($string); - break; - case "mysql": - $string = mysql_real_escape_string($string); - break; - } - - # I don't think this ever worked how it intended. - # I've tested PDO, MySQLi, and MySQL and they all - # properly escape with this disabled, but get double - # escaped with this uncommented: - # $string = str_replace('\\', '\\\\', $string); - $string = str_replace('$', '\$', $string); - - if ($quotes and !is_numeric($string)) - $string = "'".$string."'"; - - return $string; - } - - /** - * Function: year_from_datetime - * Returns the year of a datetime. - * - * Parameters: - * $datetime - DATETIME value. - */ - public function year_from_datetime($datetime) { - return when("Y", $datetime); - } - - /** - * Function: month_from_datetime - * Returns the month of a datetime. - * - * Parameters: - * $datetime - DATETIME value. - */ - public function month_from_datetime($datetime) { - return when("m", $datetime); - } - - /** - * Function: day_from_datetime - * Returns the day of a datetime. - * - * Parameters: - * $datetime - DATETIME value. - */ - public function day_from_datetime($datetime) { - return when("d", $datetime); - } - - /** - * Function: hour_from_datetime - * Returns the hour of a datetime. - * - * Parameters: - * $datetime - DATETIME value. - */ - public function hour_from_datetime($datetime) { - return when("g", $datetime); - } - - /** - * Function: minute_from_datetime - * Returns the minute of a datetime. - * - * Parameters: - * $datetime - DATETIME value. - */ - public function minute_from_datetime($datetime) { - return when("i", $datetime); - } - - /** - * Function: second_from_datetime - * Returns the second of a datetime. - * - * Parameters: - * $datetime - DATETIME value. - */ - public function second_from_datetime($datetime) { - return when("s", $datetime); - } - - /** - * Function: current - * Returns a singleton reference to the current connection. - */ - public static function & current($settings = false) { - if ($settings) { - static $loaded_settings = null; - return $loaded_settings = new self($settings); - } else { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } - } diff --git a/News/includes/class/Session.php b/News/includes/class/Session.php deleted file mode 100644 index af1dc9a..0000000 --- a/News/includes/class/Session.php +++ /dev/null @@ -1,95 +0,0 @@ -select("sessions", - "data", - array("id" => $id), - "id")->fetchColumn(); - - return fallback(self::$data, ""); - } - - /** - * Function: write - * Writes their session to the database, or updates it if it already exists. - * - * Parameters: - * $id - Session ID. - * $data - Data to write. - */ - static function write($id, $data) { - if (empty($data) or $data == self::$data) - return; - - $sql = SQL::current(); - - if ($sql->count("sessions", array("id" => $id))) - $sql->update("sessions", - array("id" => $id), - array("data" => $data, - "user_id" => Visitor::current()->id, - "updated_at" => datetime())); - else - $sql->insert("sessions", - array("id" => $id, - "data" => $data, - "user_id" => Visitor::current()->id, - "created_at" => datetime())); - } - - /** - * Function: destroy - * Destroys their session. - * - * Parameters: - * $id - Session ID. - */ - static function destroy($id) { - if (SQL::current()->delete("sessions", array("id" => $id))) - return true; - - return false; - } - - /** - * Function: gc - * Garbage collector. Removes sessions older than 30 days and sessions with no stored data. - */ - static function gc() { - SQL::current()->delete("sessions", - "created_at >= :thirty_days OR data = '' OR data IS NULL", - array(":thirty_days" => datetime(strtotime("+30 days")))); - return true; - } - } diff --git a/News/includes/class/Theme.php b/News/includes/class/Theme.php deleted file mode 100644 index ec0f802..0000000 --- a/News/includes/class/Theme.php +++ /dev/null @@ -1,332 +0,0 @@ -, and sets up the theme l10n domain. - */ - private function __construct() { - $config = Config::current(); - - # Load the theme translator - if (file_exists(THEME_DIR."/locale/".$config->locale.".mo")) - load_translator("theme", THEME_DIR."/locale/".$config->locale.".mo"); - - # Load the theme's info into the Theme class. - foreach (YAML::load(THEME_DIR."/info.yaml") as $key => $val) - $this->$key = $val; - - $this->url = THEME_URL; - } - - /** - * Function: pages_list - * Returns a simple array of list items to be used by the theme to generate a recursive array of pages. - * - * Parameters: - * $start - Page ID or slug to start at. - * $exclude - Page ID to exclude from the list. Used in the admin area. - */ - public function pages_list($start = 0, $exclude = null) { - if (isset($this->pages_list[$start])) - return $this->pages_list[$start]; - - $this->linear_children = array(); - $this->pages_flat = array(); - $this->children = array(); - $this->end_tags_for = array(); - - if ($start and !is_numeric($start)) - $begin_page = new Page(array("url" => $start)); - - $start = ($start and !is_numeric($start)) ? $begin_page->id : $start ; - - $where = ADMIN ? array("id not" => $exclude) : array("show_in_list" => true) ; - $pages = Page::find(array("where" => $where, "order" => "list_order ASC")); - - if (empty($pages)) - return $this->pages_list[$start] = array(); - - foreach ($pages as $page) - $this->end_tags_for[$page->id] = $this->children[$page->id] = array(); - - foreach ($pages as $page) - if ($page->parent_id != 0) - $this->children[$page->parent_id][] = $page; - - foreach ($pages as $page) - if ((!$start and $page->parent_id == 0) or ($start and $page->id == $start)) - $this->recurse_pages($page); - - $array = array(); - foreach ($this->pages_flat as $page) { - $array[$page->id]["has_children"] = !empty($this->children[$page->id]); - - if ($array[$page->id]["has_children"]) - $this->end_tags_for[$this->get_last_linear_child($page->id)][] = array("
", ""); - - $array[$page->id]["end_tags"] =& $this->end_tags_for[$page->id]; - $array[$page->id]["page"] = $page; - } - - return $this->pages_list[$start] = $array; - } - - /** - * Function: get_last_linear_child - * Gets the last linear child of a page. - * - * Parameters: - * $page - Page to get the last linear child of. - * $origin - Where to start. - */ - public function get_last_linear_child($page, $origin = null) { - fallback($origin, $page); - - $this->linear_children[$origin] = $page; - foreach ($this->children[$page] as $child) - $this->get_last_linear_child($child->id, $origin); - - return $this->linear_children[$origin]; - } - - /** - * Function: recurse_pages - * Prepares the pages into . - * - * Parameters: - * $page - Page to start recursion at. - */ - public function recurse_pages($page) { - $page->depth = oneof(@$page->depth, 1); - - $this->pages_flat[] = $page; - - foreach ($this->children[$page->id] as $child) { - $child->depth = $page->depth + 1; - $this->recurse_pages($child); - } - } - - /** - * Function: archive_list - * Generates an array of all of the archives, by month. - * - * Parameters: - * $limit - Amount of months to list - * $order_by - What to sort it by - * $order - "asc" or "desc" - * - * Returns: - * The array. Each entry as "month", "year", and "url" values, stored as an array. - */ - public function archives_list($limit = 0, $order_by = "created_at", $order = "desc") { - if (isset($this->archives_list["$limit,$order_by,$order"])) - return $this->archives_list["$limit,$order_by,$order"]; - - $sql = SQL::current(); - $dates = $sql->select("posts", - array("DISTINCT YEAR(created_at) AS year", - "MONTH(created_at) AS month", - "created_at AS created_at", - "COUNT(id) AS posts"), - array("status" => "public", Post::feathers()), - $order_by." ".strtoupper($order), - array(), - ($limit == 0) ? null : $limit, - null, - array("created_at")); - - $archives = array(); - $grouped = array(); - while ($date = $dates->fetchObject()) - if (isset($grouped[$date->month." ".$date->year])) - $archives[$grouped[$date->month." ".$date->year]]["count"]++; - else { - $grouped[$date->month." ".$date->year] = count($archives); - $archives[] = array("month" => $date->month, - "year" => $date->year, - "when" => $date->created_at, - "url" => url("archive/".when("Y/m/", $date->created_at)), - "count" => $date->posts); - } - - return $this->archives_list["$limit,$order_by,$order"] = $archives; - } - - /** - * Function: file_exists - * Returns whether the specified Twig file exists or not. - * - * Parameters: - * $file - The file's name - */ - public function file_exists($file) { - return file_exists(THEME_DIR."/".$file.".twig"); - } - - /** - * Function: stylesheets - * Outputs the default stylesheet links. - */ - public function stylesheets() { - $visitor = Visitor::current(); - $config = Config::current(); - $trigger = Trigger::current(); - - $stylesheets = array(); - Trigger::current()->filter($stylesheets, "stylesheets"); - - if (!empty($stylesheets)) - $stylesheets = ''; - else - $stylesheets = ""; - - if (file_exists(THEME_DIR."/style.css")) - $stylesheets = ''."\n\t\t"; - - if (!file_exists(THEME_DIR."/stylesheets/") and !file_exists(THEME_DIR."/css/")) - return $stylesheets; - - $long = (array) glob(THEME_DIR."/stylesheets/*"); - $short = (array) glob(THEME_DIR."/css/*"); - - $total = array_merge($long, $short); - foreach($total as $file) { - $path = preg_replace("/(.+)\/themes\/(.+)/", "/themes/\\2", $file); - $file = basename($file); - - if (substr_count($file, ".inc.css") or (substr($file, -4) != ".css" and substr($file, -4) != ".php")) - continue; - - if ($file == "ie.css") - $stylesheets.= ""; - - $stylesheets.= "\n\t\t"; - } - - return $stylesheets; - } - - /** - * Function: javascripts - * Outputs the default JavaScript script references. - */ - public function javascripts() { - $route = Route::current(); - - $args = ""; - foreach ($_GET as $key => $val) - if (!empty($val) and $val != $route->action) - $args.= "&".$key."=".urlencode($val); - - $config = Config::current(); - $trigger = Trigger::current(); - - $javascripts = array($config->chyrp_url."/includes/lib/gz.php?file=jquery.js", - $config->chyrp_url."/includes/lib/gz.php?file=plugins.js", - $config->chyrp_url.'/includes/javascript.php?action='.$route->action.$args); - Trigger::current()->filter($javascripts, "scripts"); - - $javascripts = ''."\n\t\t".''; - - if (file_exists(THEME_DIR."/javascripts/") or file_exists(THEME_DIR."/js/")) { - $long = (array) glob(THEME_DIR."/javascripts/*.js"); - $short = (array) glob(THEME_DIR."/js/*.js"); - - foreach(array_merge($long, $short) as $file) - if ($file and !substr_count($file, ".inc.js")) - $javascripts.= "\n\t\t".''; - - $long = (array) glob(THEME_DIR."/javascripts/*.php"); - $short = (array) glob(THEME_DIR."/js/*.php"); - foreach(array_merge($long, $short) as $file) - if ($file) - $javascripts.= "\n\t\t".''; - } - - return $javascripts; - } - - /** - * Function: feeds - * Outputs the Feed references. - */ - public function feeds() { - // Compute the URL of the per-page feed (if any): - $config = Config::current(); - $request = ($config->clean_urls) ? rtrim(Route::current()->request, "/") : fix($_SERVER['REQUEST_URI']) ; - $append = $config->clean_urls ? - "/feed" : - ((count($_GET) == 1 and Route::current()->action == "index") ? - "/?feed" : - "&feed") ; - $append.= $config->clean_urls ? - "/".urlencode($this->title) : - "&title=".urlencode($this->title) ; - - # Create basic list of links (site and page Atom feeds): - $feedurl = oneof(@$config->feed_url, url("feed")); - $pagefeedurl = $config->url.$request.$append; - $links = array(array("href" => $feedurl, "type" => "application/atom+xml", "title" => $config->name)); - if ($pagefeedurl != $feedurl) - $links[] = array("href" => $pagefeedurl, "type" => "application/atom+xml", "title" => "Current Page (if applicable)"); - - # Ask modules to pitch in by adding their own tag items to $links. - # Each item must be an array with "href" and "rel" properties (and optionally "title" and "type"): - Trigger::current()->filter($links, "links"); - - # Generate tags: - $tags = array(); - foreach ($links as $link) { - $rel = oneof(@$link["rel"], "alternate"); - $href = $link["href"]; - $type = @$link["type"]; - $title = @$link["title"]; - $tag = ''; - } - - return implode("\n\t", $tags); - } - - public function load_time() { - return timer_stop(); - } - - /** - * Function: current - * Returns a singleton reference to the current class. - */ - public static function & current() { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } diff --git a/News/includes/class/Trigger.php b/News/includes/class/Trigger.php deleted file mode 100755 index d383fee..0000000 --- a/News/includes/class/Trigger.php +++ /dev/null @@ -1,176 +0,0 @@ - $call) { - $args = func_get_args(); - $args[0] = $call; - if ($index + 1 == count($name)) - return $this->exists($call) ? call_user_func_array(array($this, "call"), $args) : $return ; - else - $return = $this->exists($call) ? call_user_func_array(array($this, "call"), $args) : $return ; - } - } - - if (!$this->exists($name)) - return false; - - $arguments = func_get_args(); - array_shift($arguments); - - $return = null; - - $this->called[$name] = array(); - if (isset($this->priorities[$name])) { # Predefined priorities? - usort($this->priorities[$name], array($this, "cmp")); - - foreach ($this->priorities[$name] as $action) { - $return = call_user_func_array($action["function"], $arguments); - $this->called[$name][] = $action["function"]; - } - } - - foreach (Modules::$instances as $module) - if (!in_array(array($module, $name), $this->called[$name]) and is_callable(array($module, $name))) - $return = call_user_func_array(array($module, $name), $arguments); - - return $return; - } - - /** - * Function: filter - * Filters a variable through a trigger's actions. Similar to , except this is stackable and is intended to - * modify something instead of inject code. - * - * Any additional arguments passed to this function are passed to the function being called. - * - * Parameters: - * &$target - The variable to filter. - * $name - The name of the trigger. - * - * Returns: - * $target, filtered through any/all actions for the trigger $name. - */ - public function filter(&$target, $name) { - if (is_array($name)) - foreach ($name as $index => $filter) { - $args = func_get_args(); - $args[0] =& $target; - $args[1] = $filter; - if ($index + 1 == count($name)) - return $target = call_user_func_array(array($this, "filter"), $args); - else - $target = call_user_func_array(array($this, "filter"), $args); - } - - if (!$this->exists($name)) - return $target; - - $arguments = func_get_args(); - array_shift($arguments); - array_shift($arguments); - - $this->called[$name] = array(); - - if (isset($this->priorities[$name]) and usort($this->priorities[$name], array($this, "cmp"))) - foreach ($this->priorities[$name] as $action) { - $call = call_user_func_array($this->called[$name][] = $action["function"], - array_merge(array(&$target), $arguments)); - $target = fallback($call, $target); - } - - foreach (Modules::$instances as $module) - if (!in_array(array($module, $name), $this->called[$name]) and is_callable(array($module, $name))) { - $call = call_user_func_array(array($module, $name), - array_merge(array(&$target), $arguments)); - $target = fallback($call, $target); - } - - return $target; - } - - /** - * Function: remove - * Unregisters a given $action from a $trigger. - * - * Parameters: - * $trigger - The trigger to unregister from. - * $action - The action name. - */ - public function remove($trigger, $action) { - foreach ($this->actions[$trigger] as $index => $func) { - if ($func == $action) { - unset($this->actions[$trigger][$key]); - return; - } - } - $this->actions[$trigger]["disabled"][] = $action; - } - - /** - * Function: exists - * Checks if there are any actions for a given $trigger. - * - * Parameters: - * $trigger - The trigger name. - * - * Returns: - * @true@ or @false@ - */ - public function exists($name) { - if (isset($this->exists[$name])) - return $this->exists[$name]; - - foreach (Modules::$instances as $module) - if (is_callable(array($module, $name))) - return $this->exists[$name] = true; - - if (isset($this->priorities[$name])) - return $this->exists[$name] = true; - - return $this->exists[$name] = false; - } - - /** - * Function: current - * Returns a singleton reference to the current class. - */ - public static function & current() { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } diff --git a/News/includes/class/Twig.php b/News/includes/class/Twig.php deleted file mode 100644 index b0891a2..0000000 --- a/News/includes/class/Twig.php +++ /dev/null @@ -1,55 +0,0 @@ -getTemplate('index.html'); - * - * You can render templates by using the render and display methods. display - * works like render just that it prints the output whereas render returns - * the generated source as string. Both accept an array as context:: - * - * echo $template->render(array('users' => get_list_of_users())); - * $template->display(array('users' => get_list_of_users())); - * - * Custom Loaders - * -------------- - * - * For many applications it's a good idea to subclass the loader to add - * support for multiple template locations. For example many applications - * support plugins and you want to allow plugins to ship themes. - * - * The easiest way is subclassing Twig_Loader and override the getFilename - * method which calculates the path to the template on the file system. - * - * - * :copyright: 2008 by Armin Ronacher. - * :license: BSD. - */ - - - if (!defined('TWIG_BASE')) - define('TWIG_BASE', dirname(__FILE__) . '/Twig'); - - define('TWIG_VERSION', '0.1-dev'); - - - // the systems we load automatically on initialization. The compiler - // and other stuff is loaded on first request. - require TWIG_BASE . '/exceptions.php'; - require TWIG_BASE . '/runtime.php'; - require TWIG_BASE . '/api.php'; diff --git a/News/includes/class/Twig/api.php b/News/includes/class/Twig/api.php deleted file mode 100644 index d103e70..0000000 --- a/News/includes/class/Twig/api.php +++ /dev/null @@ -1,192 +0,0 @@ -instance = $instance; - $this->charset = $charset; - $this->loader = $loader; - } - - /** - * Render the template with the given context and return it - * as string. - */ - public function render($context=NULL) - { - ob_start(); - $this->display($context); - return ob_get_clean(); - } - - /** - * Works like `render()` but prints the output. - */ - public function display($context=NULL) - { - global $twig_current_template; - $old = $twig_current_template; - $twig_current_template = $this; - if (is_null($context)) - $context = array(); - $this->instance->render($context); - $twig_current_template = $old; - } -} - -/** - * Baseclass for custom loaders. Subclasses have to provide a - * getFilename method. - */ -class Twig_BaseLoader -{ - public $cache; - public $charset; - - public function __construct($cache=NULL, $charset=NULL) - { - $this->cache = $cache; - $this->charset = $charset; - } - - public function getTemplate($name) - { - $cls = $this->requireTemplate($name); - return new Twig_Template(new $cls, $this->charset, $this); - } - - public function getCacheFilename($name) - { - return $this->cache . '/twig_' . md5($name) . '.cache'; - } - - public function requireTemplate($name) - { - $cls = '__TwigTemplate_' . md5($name); - if (!class_exists($cls)) { - if (is_null($this->cache)) { - $this->evalTemplate($name); - return $cls; - } - $fn = $this->getFilename($name); - if (!file_exists($fn)) - throw new Twig_TemplateNotFound($name); - $cache_fn = $this->getCacheFilename($name); - if (!file_exists($cache_fn) || - filemtime($cache_fn) < filemtime($fn)) { - twig_load_compiler(); - $fp = @fopen($cache_fn, 'wb'); - if (!$fp) { - $this->evalTemplate($name, $fn); - return $cls; - } - $compiler = new Twig_FileCompiler($fp); - $this->compileTemplate($name, $compiler, $fn); - fclose($fp); - } - include $cache_fn; - } - return $cls; - } - - public function compileTemplate($name, $compiler=NULL, $fn=NULL) - { - twig_load_compiler(); - if (is_null($compiler)) { - $compiler = new Twig_StringCompiler(); - $returnCode = true; - } - else - $returnCode = false; - if (is_null($fn)) - $fn = $this->getFilename($name); - - $node = twig_parse(file_get_contents($fn, $name), $name); - $node->compile($compiler); - if ($returnCode) - return $compiler->getCode(); - } - - private function evalTemplate($name, $fn=NULL) - { - $code = $this->compileTemplate($name, NULL, $fn); - # echo "ORIGINAL: "; - $code = preg_replace('/(?!echo twig_get_attribute.+)echo "[\\\\tn]+";/', "", $code); # Remove blank lines - #echo "STRIPPED: "; - eval('?>' . $code); - } -} - - -/** - * Helper class that loads templates. - */ -class Twig_Loader extends Twig_BaseLoader -{ - public $folder; - - public function __construct($folder, $cache=NULL, $charset=NULL) - { - parent::__construct($cache, $charset); - $this->folder = $folder; - } - - public function getFilename($name) - { - if ($name[0] == '/' or preg_match("/[a-zA-Z]:\\\/", $name)) return $name; - - $path = array(); - foreach (explode('/', $name) as $part) { - if ($part[0] != '.') - array_push($path, $part); - } - - return $this->folder . '/' . implode('/', $path) ; - } -} diff --git a/News/includes/class/Twig/ast.php b/News/includes/class/Twig/ast.php deleted file mode 100644 index 1561475..0000000 --- a/News/includes/class/Twig/ast.php +++ /dev/null @@ -1,754 +0,0 @@ -lineno = $lineno; - } - - public function compile($compiler) - { - } -} - - -class Twig_NodeList extends Twig_Node -{ - public $nodes; - - public function __construct($nodes, $lineno) - { - parent::__construct($lineno); - $this->nodes = $nodes; - } - - public function compile($compiler) - { - foreach ($this->nodes as $node) - $node->compile($compiler); - } - - public static function fromArray($array, $lineno) - { - if (count($array) == 1) - return $array[0]; - return new Twig_NodeList($array, $lineno); - } -} - - -class Twig_Module extends Twig_Node -{ - public $body; - public $extends; - public $blocks; - public $filename; - public $id; - - public function __construct($body, $extends, $blocks, $filename) - { - parent::__construct(1); - $this->body = $body; - $this->extends = $extends; - $this->blocks = $blocks; - $this->filename = $filename; - } - - public function compile($compiler) - { - $compiler->raw("extends)) { - $compiler->raw('$this->requireTemplate('); - $compiler->repr($this->extends); - $compiler->raw(");\n"); - } - $compiler->raw('class __TwigTemplate_' . md5($this->filename)); - if (!is_null($this->extends)) { - $parent = md5($this->extends); - $compiler->raw(" extends __TwigTemplate_$parent {\n"); - } - else { - $compiler->raw(" {\npublic function render(\$context) {\n"); - $this->body->compile($compiler); - $compiler->raw("}\n"); - } - - foreach ($this->blocks as $node) - $node->compile($compiler); - - $compiler->raw("}\n"); - } -} - - -class Twig_Print extends Twig_Node -{ - public $expr; - - public function __construct($expr, $lineno) - { - parent::__construct($lineno); - $this->expr = $expr; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->raw('echo '); - $this->expr->compile($compiler); - $compiler->raw(";\n"); - } -} - - -class Twig_Text extends Twig_Node -{ - public $data; - - public function __construct($data, $lineno) - { - parent::__construct($lineno); - $this->data = $data; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->raw('echo '); - $compiler->string($this->data); - $compiler->raw(";\n"); - } -} - - -class Twig_ForLoop extends Twig_Node -{ - public $is_multitarget; - public $item; - public $seq; - public $body; - public $else; - - public function __construct($is_multitarget, $item, $seq, $body, $else, - $lineno) - { - parent::__construct($lineno); - $this->is_multitarget = $is_multitarget; - $this->item = $item; - $this->seq = $seq; - $this->body = $body; - $this->else = $else; - $this->lineno = $lineno; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->pushContext(); - $compiler->raw('foreach (twig_iterate($context, '); - $this->seq->compile($compiler); - $compiler->raw(") as \$iterator) {\n"); - if ($this->is_multitarget) { - $compiler->raw('twig_set_loop_context_multitarget($context, ' . - '$iterator, array('); - $idx = 0; - foreach ($this->item as $node) { - if ($idx++) - $compiler->raw(', '); - $compiler->repr($node->name); - } - $compiler->raw("));\n"); - } - else { - $compiler->raw('twig_set_loop_context($context, $iterator, '); - $compiler->repr($this->item->name); - $compiler->raw(");\n"); - } - $this->body->compile($compiler); - $compiler->raw("}\n"); - if (!is_null($this->else)) { - $compiler->raw("if (!\$context['loop']['iterated']) {\n"); - $this->else->compile($compiler); - $compiler->raw('}'); - } - $compiler->popContext(); - } -} - -class Twig_PaginateLoop extends Twig_Node -{ - public $item; - public $seq; - public $body; - public $else; - - public function __construct($item, $per_page, $target, - $as, $body, $else, $lineno) - { - parent::__construct($lineno); - $this->item = $item; - $this->per_page = $per_page; - $this->seq = $target; - $this->as = $as; - $this->body = $body; - $this->else = $else; - $this->lineno = $lineno; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->pushContext(); - $compiler->raw('twig_paginate($context,'); - $compiler->raw('"'.$this->as->name.'", '); - if (isset($this->seq->node) and isset($this->seq->attr)) { - $compiler->raw('array($context["::parent"]["'); - $compiler->raw($this->seq->node->name.'"],'); - $compiler->raw('"'.$this->seq->attr->value.'")'); - } else - $this->seq->compile($compiler); - $compiler->raw(', '); - $this->per_page->compile($compiler); - $compiler->raw(");\n"); - $compiler->raw('foreach (twig_iterate($context,'); - $compiler->raw(' $context["::parent"]["'.$this->as->name); - $compiler->raw("\"]->paginated) as \$iterator) {\n"); - $compiler->raw('twig_set_loop_context($context, $iterator, '); - $compiler->repr($this->item->name); - $compiler->raw(");\n"); - $this->body->compile($compiler); - $compiler->raw("}\n"); - if (!is_null($this->else)) { - $compiler->raw("if (!\$context['loop']['iterated']) {\n"); - $this->else->compile($compiler); - $compiler->raw('}'); - } - $compiler->popContext(); - } -} - - -class Twig_IfCondition extends Twig_Node -{ - public $tests; - public $else; - - public function __construct($tests, $else, $lineno) - { - parent::__construct($lineno); - $this->tests = $tests; - $this->else = $else; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $idx = 0; - foreach ($this->tests as $test) { - $compiler->raw(($idx++ ? "}\nelse" : '') . 'if ('); - $test[0]->compile($compiler); - $compiler->raw(") {\n"); - $test[1]->compile($compiler); - } - if (!is_null($this->else)) { - $compiler->raw("} else {\n"); - $this->else->compile($compiler); - } - $compiler->raw("}\n"); - } -} - - -class Twig_Block extends Twig_Node -{ - public $name; - public $body; - public $parent; - - public function __construct($name, $body, $lineno, $parent=NULL) - { - parent::__construct($lineno); - $this->name = $name; - $this->body = $body; - $this->parent = $parent; - } - - public function replace($other) - { - $this->body = $other->body; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->format('public function block_%s($context) {' . "\n", - $this->name); - if (!is_null($this->parent)) - $compiler->raw('$context[\'::superblock\'] = array($this, ' . - "'parent::block_$this->name');\n"); - $this->body->compile($compiler); - $compiler->format("}\n\n"); - } -} - - -class Twig_BlockReference extends Twig_Node -{ - public $name; - - public function __construct($name, $lineno) - { - parent::__construct($lineno); - $this->name = $name; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->format('$this->block_%s($context);' . "\n", $this->name); - } -} - - -class Twig_Super extends Twig_Node -{ - public $block_name; - - public function __construct($block_name, $lineno) - { - parent::__construct($lineno); - $this->block_name = $block_name; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->raw('parent::block_' . $this->block_name . '($context);' . "\n"); - } -} - - -class Twig_Include extends Twig_Node -{ - public $expr; - - public function __construct($expr, $lineno) - { - parent::__construct($lineno); - $this->expr = $expr; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->raw('twig_get_current_template()->loader->getTemplate('); - $this->expr->compile($compiler); - $compiler->raw(')->display($context);' . "\n"); - } -} - - -class Twig_URL extends Twig_Node -{ - public $expr; - - public function __construct($expr, $cont, $lineno) - { - parent::__construct($lineno); - $this->expr = $expr; - $this->cont = $cont; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->raw('echo url('); - $this->expr->compile($compiler); - - if (!empty($this->cont) and class_exists($this->cont->name."Controller") and is_callable(array($this->cont->name."Controller", "current"))) - $compiler->raw(", ".$this->cont->name."Controller::current()"); - - $compiler->raw(');'."\n"); - } -} - - -class Twig_AdminURL extends Twig_Node -{ - public $expr; - - public function __construct($expr, $lineno) - { - parent::__construct($lineno); - $this->expr = $expr; - } - - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $compiler->raw('echo fix(Config::current()->chyrp_url."/admin/?action=".('); - $this->expr->compile($compiler); - $compiler->raw('));'."\n"); - } -} - - -class Twig_Expression extends Twig_Node -{ - -} - - -class Twig_ConditionalExpression extends Twig_Expression -{ - public $expr1; - public $expr2; - public $expr3; - - public function __construct($expr1, $expr2, $expr3, $lineno) - { - parent::__construct($lineno); - $this->expr1 = $expr1; - $this->expr2 = $expr2; - $this->expr3 = $expr3; - } - - public function compile($compiler) - { - $compiler->raw('('); - $this->expr1->compile($compiler); - $compiler->raw(') ? ('); - $this->expr2->compile($compiler); - $compiler->raw(') ; ('); - $this->expr3->compile($compiler); - $compiler->raw(')'); - } -} - - -class Twig_BinaryExpression extends Twig_Expression -{ - public $left; - public $right; - - public function __construct($left, $right, $lineno) - { - parent::__construct($lineno); - $this->left = $left; - $this->right = $right; - } - - public function compile($compiler) - { - $compiler->raw('('); - $this->left->compile($compiler); - $compiler->raw(') '); - $this->operator($compiler); - $compiler->raw(' ('); - $this->right->compile($compiler); - $compiler->raw(')'); - } -} - - -class Twig_OrExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('||'); - } -} - - -class Twig_AndExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('&&'); - } -} - - -class Twig_AddExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('+'); - } -} - - -class Twig_SubExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('-'); - } -} - - -class Twig_ConcatExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('.'); - } -} - - -class Twig_MulExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('*'); - } -} - - -class Twig_DivExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('/'); - } -} - - -class Twig_ModExpression extends Twig_BinaryExpression -{ - public function operator($compiler) - { - return $compiler->raw('%'); - } -} - - -class Twig_CompareExpression extends Twig_Expression -{ - public $expr; - public $ops; - - public function __construct($expr, $ops, $lineno) - { - parent::__construct($lineno); - $this->expr = $expr; - $this->ops = $ops; - } - - public function compile($compiler) - { - $this->expr->compile($compiler); - $i = 0; - foreach ($this->ops as $op) { - if ($i) - $compiler->raw(' && ($tmp' . $i); - list($op, $node) = $op; - $compiler->raw(' ' . $op . ' '); - $compiler->raw('($tmp' . ++$i . ' = '); - $node->compile($compiler); - $compiler->raw(')'); - } - if ($i > 1) - $compiler->raw(')'); - } -} - - -class Twig_UnaryExpression extends Twig_Expression -{ - public $node; - - public function __construct($node, $lineno) - { - parent::__construct($lineno); - $this->node = $node; - } - - public function compile($compiler) - { - $compiler->raw('('); - $this->operator($compiler); - $this->node->compile($compiler); - $compiler->raw(')'); - } -} - - -class Twig_NotExpression extends Twig_UnaryExpression -{ - public function operator($compiler) - { - $compiler->raw('!'); - } -} - - -class Twig_NegExpression extends Twig_UnaryExpression -{ - public function operator($compiler) - { - $compiler->raw('-'); - } -} - - -class Twig_PosExpression extends Twig_UnaryExpression -{ - public function operator($compiler) - { - $compiler->raw('+'); - } -} - - -class Twig_Constant extends Twig_Expression -{ - public $value; - - public function __construct($value, $lineno) - { - parent::__construct($lineno); - $this->value = $value; - } - - public function compile($compiler) - { - $compiler->repr($this->value); - } -} - - -class Twig_NameExpression extends Twig_Expression -{ - public $name; - - public function __construct($name, $lineno) - { - parent::__construct($lineno); - $this->name = $name; - } - - public function compile($compiler) - { - $compiler->format('(isset($context[\'%s\']) ? $context[\'%s\'] ' . - ': NULL)', $this->name, $this->name); - } -} - - -class Twig_AssignNameExpression extends Twig_NameExpression -{ - - public function compile($compiler) - { - $compiler->format('$context[\'%s\']', $this->name); - } -} - - -class Twig_GetAttrExpression extends Twig_Expression -{ - public $node; - public $attr; - - public function __construct($node, $attr, $lineno, $token_value) - { - parent::__construct($lineno); - $this->node = $node; - $this->attr = $attr; - $this->token_value = $token_value; - } - - public function compile($compiler) - { - $compiler->raw('twig_get_attribute('); - $this->node->compile($compiler); - $compiler->raw(', '); - $this->attr->compile($compiler); - if ($this->token_value == "[") # Don't look for functions if they're using foo[bar] - $compiler->raw(', false'); - $compiler->raw(')'); - } -} - - -class Twig_MethodCallExpression extends Twig_Expression -{ - public $node; - public $method; - public $arguments; - - public function __construct($node, $method, $arguments, $lineno) - { - parent::__construct($lineno); - $this->node = $node; - $this->method = $method; - $this->arguments = $arguments; - } - - public function compile($compiler) - { - $compiler->raw('call_user_func(array('); - $this->node->compile($compiler); - $compiler->raw(', '); - $this->method->compile($compiler); - $compiler->raw(')'); - foreach ($this->arguments as $argument) { - $compiler->raw(', '); - $argument->compile($compiler); - } - $compiler->raw(')'); - } -} - - -class Twig_FilterExpression extends Twig_Expression -{ - public $node; - public $filters; - - public function __construct($node, $filters, $lineno) - { - parent::__construct($lineno); - $this->node = $node; - $this->filters = $filters; - } - - public function compile($compiler) - { - global $twig_filters; - $postponed = array(); - for ($i = count($this->filters) - 1; $i >= 0; --$i) { - list($name, $attrs) = $this->filters[$i]; - if (!isset($twig_filters[$name])) { - $compiler->raw('twig_missing_filter('); - $compiler->repr($name); - $compiler->raw(', '); - } - else - $compiler->raw($twig_filters[$name] . '('); - $postponed[] = $attrs; - } - $this->node->compile($compiler); - foreach (array_reverse($postponed) as $attributes) { - foreach ($attributes as $node) { - $compiler->raw(', '); - $node->compile($compiler); - } - $compiler->raw(')'); - } - } -} diff --git a/News/includes/class/Twig/compiler.php b/News/includes/class/Twig/compiler.php deleted file mode 100644 index 96ffc7b..0000000 --- a/News/includes/class/Twig/compiler.php +++ /dev/null @@ -1,133 +0,0 @@ -compile($compiler); - if (is_null($fp)) - return $compiler->getCode(); -} - - -class Twig_Compiler -{ - private $last_lineno; - - public function __construct() - { - $this->last_lineno = NULL; - } - - public function format() - { - $arguments = func_get_args(); - $this->raw(call_user_func_array('sprintf', $arguments)); - } - - public function string($value) - { - $this->format('"%s"', addcslashes($value, "\t\"")); - } - - public function repr($value) - { - if (is_int($value) || is_float($value)) - $this->raw($value); - else if (is_null($value)) - $this->raw('NULL'); - else if (is_bool($value)) - $this->raw($value ? 'true' : 'false'); - else if (is_array($value)) { - $this->raw('array('); - $i = 0; - foreach ($value as $key => $value) { - if ($i++) - $this->raw(', '); - $this->repr($key); - $this->raw(' => '); - $this->repr($value); - } - $this->raw(')'); - } - else - $this->string($value); - } - - public function pushContext() - { - $this->raw('$context[\'::parent\'] = $parent = $context;'. "\n"); - } - - public function popContext() - { - $this->raw('$context = $context[\'::parent\'];'. "\n"); - } - - public function addDebugInfo($node) - { - if ($node->lineno != $this->last_lineno) { - $this->last_lineno = $node->lineno; - $this->raw("/* LINE:$node->lineno */\n"); - } - } -} - - -class Twig_FileCompiler extends Twig_Compiler -{ - private $fp; - - public function __construct($fp) - { - parent::__construct(); - $this->fp = $fp; - } - - public function raw($string) - { - fwrite($this->fp, $string); - } -} - - -class Twig_StringCompiler extends Twig_Compiler -{ - private $source; - - public function __construct() - { - parent::__construct(); - $this->source = ''; - } - - public function raw($string) - { - $this->source .= $string; - } - - public function getCode() - { - return $this->source; - } -} diff --git a/News/includes/class/Twig/exceptions.php b/News/includes/class/Twig/exceptions.php deleted file mode 100644 index a340523..0000000 --- a/News/includes/class/Twig/exceptions.php +++ /dev/null @@ -1,66 +0,0 @@ -lineno = $lineno; - $this->filename = $filename; - } -} - - -/** - * Thrown when Twig encounters an exception at runtime in the Twig - * core. - */ -class Twig_RuntimeError extends Twig_Exception -{ - public function __construct($message) - { - parent::__construct($message); - } -} - - -/** - * Raised if the loader is unable to find a template. - */ -class Twig_TemplateNotFound extends Twig_Exception -{ - public $name; - - public function __construct($name) - { - parent::__construct('Template not found: ' . $name); - $this->name = $name; - } -} diff --git a/News/includes/class/Twig/lexer.php b/News/includes/class/Twig/lexer.php deleted file mode 100644 index 18d536a..0000000 --- a/News/includes/class/Twig/lexer.php +++ /dev/null @@ -1,430 +0,0 @@ -=?|[!=]=|[(){}.,%*\/+~|-]|\[|\]/A'; - - public function __construct($code, $filename=NULL) - { - $this->code = preg_replace('/(\r\n|\r|\n)/', '\n', $code); - $this->filename = $filename; - $this->cursor = 0; - $this->lineno = 1; - $this->pushedBack = array(); - $this->end = strlen($this->code); - $this->position = self::POSITION_DATA; - } - - /** - * parse the nex token and return it. - */ - public function nextToken() - { - // do we have tokens pushed back? get one - if (!empty($this->pushedBack)) - return array_shift($this->pushedBack); - // have we reached the end of the code? - if ($this->cursor >= $this->end) - return Twig_Token::EOF($this->lineno); - // otherwise dispatch to the lexing functions depending - // on our current position in the code. - switch ($this->position) { - case self::POSITION_DATA: - $tokens = $this->lexData(); break; - case self::POSITION_BLOCK: - $tokens = $this->lexBlock(); break; - case self::POSITION_VAR: - $tokens = $this->lexVar(); break; - } - - // if the return value is not an array it's a token - if (!is_array($tokens)) - return $tokens; - // empty array, call again - else if (empty($tokens)) - return $this->nextToken(); - // if we have multiple items we push them to the buffer - else if (count($tokens) > 1) { - $first = array_shift($tokens); - $this->pushedBack = $tokens; - return $first; - } - // otherwise return the first item of the array. - return $tokens[0]; - } - - private function lexData() - { - $match = NULL; - - // if no matches are left we return the rest of the template - // as simple text token - if (!preg_match('/(.*?)(\{[%#]|\$(?!\$))/A', $this->code, $match, - NULL, $this->cursor)) { - $rv = Twig_Token::Text(substr($this->code, $this->cursor), - $this->lineno); - $this->cursor = $this->end; - return $rv; - } - $this->cursor += strlen($match[0]); - - // update the lineno on the instance - $lineno = $this->lineno; - $this->lineno += substr_count($match[0], '\n'); - - // push the template text first - $text = $match[1]; - if (!empty($text)) { - $result = array(Twig_Token::Text($text, $lineno)); - $lineno += substr_count($text, '\n'); - } - else - $result = array(); - - // block start token, let's return a token for that. - if (($token = $match[2]) !== '$') { - // if our section is a comment, just return the text - if ($token[1] == '#') { - if (!preg_match('/.*?#\}/A', $this->code, $match, - NULL, $this->cursor)) - throw new Twig_SyntaxError('unclosed comment', - $this->lineno); - $this->cursor += strlen($match[0]); - $this->lineno += substr_count($match[0], '\n'); - return $result; - } - $result[] = new Twig_Token(Twig_Token::BLOCK_START_TYPE, - '', $lineno); - $this->position = self::POSITION_BLOCK; - } - - // quoted block - else if (isset($this->code[$this->cursor]) && - $this->code[$this->cursor] == '{') { - $this->cursor++; - $result[] = new Twig_Token(Twig_Token::VAR_START_TYPE, - '', $lineno); - $this->position = self::POSITION_VAR; - } - - // inline variable expressions. If there is no name next we - // fail silently. $ 42 could be common so no need to be a - // dickhead. - else if (preg_match(self::REGEX_NAME, $this->code, $match, - NULL, $this->cursor)) { - $result[] = new Twig_Token(Twig_Token::VAR_START_TYPE, - '', $lineno); - $result[] = Twig_Token::Name($match[0], $lineno); - $this->cursor += strlen($match[0]); - - // allow attribute lookup - while (isset($this->code[$this->cursor]) && - $this->code[$this->cursor] === '.') { - ++$this->cursor; - $result[] = Twig_Token::Operator('.', $this->lineno); - if (preg_match(self::REGEX_NAME, $this->code, - $match, NULL, $this->cursor)) { - $this->cursor += strlen($match[0]); - $result[] = Twig_Token::Name($match[0], - $this->lineno); - } - else if (preg_match(self::REGEX_NUMBER, $this->code, - $match, NULL, $this->cursor)) { - $this->cursor += strlen($match[0]); - $result[] = Twig_Token::Number($match[0], - $this->lineno); - } - else { - --$this->cursor; - break; - } - } - $result[] = new Twig_Token(Twig_Token::VAR_END_TYPE, - '', $lineno); - } - - return $result; - } - - private function lexBlock() - { - $match = NULL; - if (preg_match('/\s*%\}/A', $this->code, $match, NULL, $this->cursor)) { - $this->cursor += strlen($match[0]); - $lineno = $this->lineno; - $this->lineno += substr_count($match[0], '\n'); - $this->position = self::POSITION_DATA; - return new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $lineno); - } - return $this->lexExpression(); - } - - private function lexVar() - { - $match = NULL; - if (preg_match('/\s*\}/A', $this->code, $match, NULL, $this->cursor)) { - $this->cursor += strlen($match[0]); - $lineno = $this->lineno; - $this->lineno += substr_count($match[0], '\n'); - $this->position = self::POSITION_DATA; - return new Twig_Token(Twig_Token::VAR_END_TYPE, '', $lineno); - } - return $this->lexExpression(); - } - - private function lexExpression() - { - $match = NULL; - - // skip whitespace - while (preg_match('/\s+/A', $this->code, $match, NULL, - $this->cursor)) { - $this->cursor += strlen($match[0]); - $this->lineno += substr_count($match[0], '\n'); - } - - // sanity check - if ($this->cursor >= $this->end) - throw new Twig_SyntaxError('unexpected end of stream', - $this->lineno, $this->filename); - - // first parse operators - if (preg_match(self::REGEX_OPERATOR, $this->code, $match, NULL, - $this->cursor)) { - $this->cursor += strlen($match[0]); - return Twig_Token::Operator($match[0], $this->lineno); - } - - // now names - if (preg_match(self::REGEX_NAME, $this->code, $match, NULL, - $this->cursor)) { - $this->cursor += strlen($match[0]); - return Twig_Token::Name($match[0], $this->lineno); - } - - // then numbers - else if (preg_match(self::REGEX_NUMBER, $this->code, $match, - NULL, $this->cursor)) { - $this->cursor += strlen($match[0]); - $value = (float)$match[0]; - if ((int)$value === $value) - $value = (int)$value; - return Twig_Token::Number($value, $this->lineno); - } - - // and finally strings - else if (preg_match(self::REGEX_STRING, $this->code, $match, - NULL, $this->cursor)) { - $this->cursor += strlen($match[0]); - $this->lineno += substr_count($match[0], '\n'); - $value = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); - return Twig_Token::String($value, $this->lineno); - } - - // unlexable - throw new Twig_SyntaxError("Unexpected character '" . - $this->code[$this->cursor] . "'.", - $this->lineno, $this->filename); - } -} - - -/** - * Wrapper around a lexer for simplified token access. - */ -class Twig_TokenStream -{ - private $pushed; - private $lexer; - public $filename; - public $current; - public $eof; - - public function __construct($lexer, $filename) - { - $this->pushed = array(); - $this->lexer = $lexer; - $this->filename = $filename; - $this->next(); - } - - public function push($token) - { - $this->pushed[] = $token; - } - - /** - * set the pointer to the next token and return the old one. - */ - public function next() - { - if (!empty($this->pushed)) - $token = array_shift($this->pushed); - else - $token = $this->lexer->nextToken(); - $old = $this->current; - $this->current = $token; - $this->eof = $token->type === Twig_Token::EOF_TYPE; - return $old; - } - - /** - * Look at the next token. - */ - public function look() - { - $old = $this->next(); - $new = $this->current; - $this->push($old); - $this->push($new); - return $new; - } - - /** - * Skip some tokens. - */ - public function skip($times=1) - { - for ($i = 0; $i < $times; ++$i) - $this->next(); - } - - /** - * expect a token (like $token->test()) and return it or raise - * a syntax error. - */ - public function expect($primary, $secondary=NULL) - { - $token = $this->current; - if (!$token->test($primary, $secondary)) - throw new Twig_SyntaxError('unexpected token', - $this->current->lineno); - $this->next(); - return $token; - } - - /** - * Forward that call to the current token. - */ - public function test($primary, $secondary=NULL) - { - return $this->current->test($primary, $secondary); - } -} - - -/** - * Simple struct for tokens. - */ -class Twig_Token -{ - public $type; - public $value; - public $lineno; - - const TEXT_TYPE = 0; - const EOF_TYPE = -1; - const BLOCK_START_TYPE = 1; - const VAR_START_TYPE = 2; - const BLOCK_END_TYPE = 3; - const VAR_END_TYPE = 4; - const NAME_TYPE = 5; - const NUMBER_TYPE = 6; - const STRING_TYPE = 7; - const OPERATOR_TYPE = 8; - - public function __construct($type, $value, $lineno) - { - $this->type = $type; - $this->value = $value; - $this->lineno = $lineno; - } - - /** - * Test the current token for a type. The first argument is the type - * of the token (if not given Twig_Token::NAME_NAME), the second the - * value of the token (if not given value is not checked). - * the token value can be an array if multiple checks shoudl be - * performed. - */ - public function test($type, $values=NULL) - { - if (is_null($values) && !is_int($type)) { - $values = $type; - $type = self::NAME_TYPE; - } - return ($this->type === $type) && ( - is_null($values) || - (is_array($values) && in_array($this->value, $values)) || - $this->value == $values - ); - } - - public static function Text($value, $lineno) - { - return new Twig_Token(self::TEXT_TYPE, $value, $lineno); - } - - public static function EOF($lineno) - { - return new Twig_Token(self::EOF_TYPE, '', $lineno); - } - - public static function Name($value, $lineno) - { - return new Twig_Token(self::NAME_TYPE, $value, $lineno); - } - - public static function Number($value, $lineno) - { - return new Twig_Token(self::NUMBER_TYPE, $value, $lineno); - } - - public static function String($value, $lineno) - { - return new Twig_Token(self::STRING_TYPE, $value, $lineno); - } - - public static function Operator($value, $lineno) - { - return new Twig_Token(self::OPERATOR_TYPE, $value, $lineno); - } -} diff --git a/News/includes/class/Twig/parser.php b/News/includes/class/Twig/parser.php deleted file mode 100644 index b3839da..0000000 --- a/News/includes/class/Twig/parser.php +++ /dev/null @@ -1,603 +0,0 @@ -parse(); -} - - -class Twig_Parser -{ - public $stream; - public $blocks; - public $extends; - public $current_block; - private $handlers; - - public function __construct($stream) - { - $this->stream = $stream; - $this->extends = NULL; - $this->blocks = array(); - $this->current_block = NULL; - $this->handlers = array( - 'for' => array($this, 'parseForLoop'), - 'if' => array($this, 'parseIfCondition'), - 'extends' => array($this, 'parseExtends'), - 'include' => array($this, 'parseInclude'), - 'block' => array($this, 'parseBlock'), - 'super' => array($this, 'parseSuper'), - - # Chyrp specific extensions - 'url' => array($this, 'parseURL'), - 'admin' => array($this, 'parseAdminURL'), - 'paginate' => array($this, 'parsePaginate') - ); - } - - public function parseForLoop($token) - { - $lineno = $token->lineno; - list($is_multitarget, $item) = $this->parseAssignmentExpression(); - $this->stream->expect('in'); - $seq = $this->parseExpression(); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->subparse(array($this, 'decideForFork')); - if ($this->stream->next()->value == 'else') { - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->subparse(array($this, 'decideForEnd'), true); - } - else - $else = NULL; - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_ForLoop($is_multitarget, $item, $seq, $body, $else, - $lineno); - } - - public function parsePaginate($token) - { - $lineno = $token->lineno; - - $per_page = $this->parseExpression(); - $as = $this->parseExpression(); - $this->stream->expect('in'); - $loop = $this->parseExpression(); - $this->stream->expect('as'); - $item = $this->parseExpression(); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->subparse(array($this, 'decidePaginateFork')); - if ($this->stream->next()->value == 'else') { - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->subparse(array($this, 'decidePaginateEnd'), true); - } - else - $else = NULL; - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_PaginateLoop($item, $per_page, - $loop, $as, $body, $else, $lineno); - } - - public function decideForFork($token) - { - return $token->test(array('else', 'endfor')); - } - - public function decideForEnd($token) - { - return $token->test('endfor'); - } - - public function decidePaginateFork($token) - { - return $token->test(array('else', 'endpaginate')); - } - - public function decidePaginateEnd($token) - { - return $token->test('endpaginate'); - } - - public function parseIfCondition($token) - { - $lineno = $token->lineno; - $expr = $this->parseExpression(); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->subparse(array($this, 'decideIfFork')); - $tests = array(array($expr, $body)); - $else = NULL; - - $end = false; - while (!$end) - switch ($this->stream->next()->value) { - case 'else': - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->subparse(array($this, 'decideIfEnd')); - break; - case 'elseif': - $expr = $this->parseExpression(); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->subparse(array($this, 'decideIfFork')); - $tests[] = array($expr, $body); - break; - case 'endif': - $end = true; - break; - } - - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_IfCondition($tests, $else, $lineno); - } - - public function decideIfFork($token) - { - return $token->test(array('elseif', 'else', 'endif')); - } - - public function decideIfEnd($token) - { - return $token->test(array('endif')); - } - - public function parseBlock($token) - { - $lineno = $token->lineno; - $name = $this->stream->expect(Twig_Token::NAME_TYPE)->value; - if (isset($this->blocks[$name])) - throw new Twig_SyntaxError("block '$name' defined twice.", - $lineno); - $this->current_block = $name; - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->subparse(array($this, 'decideBlockEnd'), true); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - $block = new Twig_Block($name, $body, $lineno); - $this->blocks[$name] = $block; - $this->current_block = NULL; - return new Twig_BlockReference($name, $lineno); - } - - public function decideBlockEnd($token) - { - return $token->test('endblock'); - } - - public function parseExtends($token) - { - $lineno = $token->lineno; - if (!is_null($this->extends)) - throw new Twig_SyntaxError('multiple extend tags', $lineno); - $this->extends = $this->stream->expect(Twig_Token::STRING_TYPE)->value; - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return NULL; - } - - public function parseInclude($token) - { - $expr = $this->parseExpression(); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Include($expr, $token->lineno); - } - - public function parseSuper($token) - { - if (is_null($this->current_block)) - throw new Twig_SyntaxError('super outside block', $token->lineno); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Super($this->current_block, $token->lineno); - } - - public function parseURL($token) - { - $expr = $this->parseExpression(); - - if ($this->stream->test("in")) { - $this->parseExpression(); - $cont = $this->parseExpression(); - } else - $cont = null; - - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_URL($expr, $cont, $token->lineno); - } - - public function parseAdminURL($token) - { - $expr = $this->parseExpression(); - $this->stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_AdminURL($expr, $token->lineno); - } - - public function parseExpression() - { - return $this->parseConditionalExpression(); - } - - public function parseConditionalExpression() - { - $lineno = $this->stream->current->lineno; - $expr1 = $this->parseOrExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '?')) { - $this->stream->next(); - $expr2 = $this->parseOrExpression(); - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ':'); - $expr3 = $this->parseConditionalExpression(); - $expr1 = new Twig_ConditionalExpression($expr1, $expr2, $expr3, - $this->lineno); - $lineno = $this->stream->current->lineno; - } - return $expr1; - } - - public function parseOrExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseAndExpression(); - while ($this->stream->test('or')) { - $this->stream->next(); - $right = $this->parseAndExpression(); - $left = new Twig_OrExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseAndExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseCompareExpression(); - while ($this->stream->test('and')) { - $this->stream->next(); - $right = $this->parseCompareExpression(); - $left = new Twig_AndExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseCompareExpression() - { - static $operators = array('==', '!=', '<', '>', '>=', '<='); - $lineno = $this->stream->current->lineno; - $expr = $this->parseAddExpression(); - $ops = array(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, $operators)) - $ops[] = array($this->stream->next()->value, - $this->parseAddExpression()); - - if (empty($ops)) - return $expr; - return new Twig_CompareExpression($expr, $ops, $lineno); - } - - public function parseAddExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseSubExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '+')) { - $this->stream->next(); - $right = $this->parseSubExpression(); - $left = new Twig_AddExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseSubExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseConcatExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '-')) { - $this->stream->next(); - $right = $this->parseConcatExpression(); - $left = new Twig_SubExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseConcatExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseMulExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '~')) { - $this->stream->next(); - $right = $this->parseMulExpression(); - $left = new Twig_ConcatExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseMulExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseDivExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '*')) { - $this->stream->next(); - $right = $this->parseDivExpression(); - $left = new Twig_MulExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseDivExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseModExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '/')) { - $this->stream->next(); - $right = $this->parseModExpression(); - $left = new Twig_DivExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseModExpression() - { - $lineno = $this->stream->current->lineno; - $left = $this->parseUnaryExpression(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '%')) { - $this->stream->next(); - $right = $this->parseUnaryExpression(); - $left = new Twig_ModExpression($left, $right, $lineno); - $lineno = $this->stream->current->lineno; - } - return $left; - } - - public function parseUnaryExpression() - { - if ($this->stream->test('not')) - return $this->parseNotExpression(); - if ($this->stream->current->type == Twig_Token::OPERATOR_TYPE) { - switch ($this->stream->current->value) { - case '-': - return $this->parseNegExpression(); - case '+': - return $this->parsePosExpression(); - } - } - return $this->parsePrimaryExpression(); - } - - public function parseNotExpression() - { - $token = $this->stream->next(); - $node = $this->parseUnaryExpression(); - return new Twig_NotExpression($node, $token->lineno); - } - - public function parseNegExpression() - { - $token = $this->stream->next(); - $node = $this->parseUnaryExpression(); - return new Twig_NegExpression($node, $token->lineno); - } - - public function parsePosExpression() - { - $token = $this->stream->next(); - $node = $this->parseUnaryExpression(); - return new Twig_PosExpression($node, $token->lineno); - } - - public function parsePrimaryExpression($assignment=false) - { - $token = $this->stream->current; - switch ($token->type) { - case Twig_Token::NAME_TYPE: - $this->stream->next(); - switch ($token->value) { - case 'true': - $node = new Twig_Constant(true, $token->lineno); - break; - case 'false': - $node = new Twig_Constant(false, $token->lineno); - break; - case 'none': - $node = new Twig_Constant(NULL, $token->lineno); - break; - default: - $cls = $assignment ? 'Twig_AssignNameExpression' - : 'Twig_NameExpression'; - $node = new $cls($token->value, $token->lineno); - } - break; - case Twig_Token::NUMBER_TYPE: - case Twig_Token::STRING_TYPE: - $this->stream->next(); - $node = new Twig_Constant($token->value, $token->lineno); - break; - default: - if ($token->test(Twig_Token::OPERATOR_TYPE, '(')) { - $this->stream->next(); - $node = $this->parseExpression(); - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ')'); - } - else - throw new Twig_SyntaxError('unexpected token', - $token->lineno); - } - if (!$assignment) - $node = $this->parsePostfixExpression($node); - return $node; - } - - public function parsePostfixExpression($node) - { - $stop = false; - while (!$stop && $this->stream->current->type == - Twig_Token::OPERATOR_TYPE) - switch ($this->stream->current->value) { - case '.': - case '[': - $node = $this->parseSubscriptExpression($node); - break; - case '|': - $node = $this->parseFilterExpression($node); - break; - default: - $stop = true; - break; - } - return $node; - } - - public function parseSubscriptExpression($node) - { - $token = $this->stream->next(); - $lineno = $token->lineno; - if ($token->value == '.') { - $token = $this->stream->next(); - if ($token->type == Twig_Token::NAME_TYPE || - $token->type == Twig_Token::NUMBER_TYPE) - $arg = new Twig_Constant($token->value, $lineno); - else - throw new Twig_SyntaxError('expected name or number', - $lineno); - } - else { - $arg = $this->parseExpression(); - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ']'); - } - - if (!$this->stream->test(Twig_Token::OPERATOR_TYPE, '(')) - return new Twig_GetAttrExpression($node, $arg, $lineno, $token->value); - - /* sounds like something wants to call a member with some - arguments. Let's parse the parameters */ - $this->stream->next(); - $arguments = array(); - while (!$this->stream->test(Twig_Token::OPERATOR_TYPE, ')')) { - if (count($arguments)) - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ','); - $arguments[] = $this->parseExpression(); - } - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ')'); - return new Twig_MethodCallExpression($node, $arg, $arguments, $lineno); - } - - public function parseFilterExpression($node) - { - $lineno = $this->stream->current->lineno; - $filters = array(); - while ($this->stream->test(Twig_Token::OPERATOR_TYPE, '|')) { - $this->stream->next(); - $token = $this->stream->expect(Twig_Token::NAME_TYPE); - $args = array(); - if ($this->stream->test( - Twig_Token::OPERATOR_TYPE, '(')) { - $this->stream->next(); - while (!$this->stream->test( - Twig_Token::OPERATOR_TYPE, ')')) { - if (!empty($args)) - $this->stream->expect( - Twig_Token::OPERATOR_TYPE, ','); - $args[] = $this->parseExpression(); - } - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ')'); - } - $filters[] = array($token->value, $args); - } - return new Twig_FilterExpression($node, $filters, $lineno); - } - - public function parseAssignmentExpression() - { - $lineno = $this->stream->current->lineno; - $targets = array(); - $is_multitarget = false; - while (true) { - if (!empty($targets)) - $this->stream->expect(Twig_Token::OPERATOR_TYPE, ','); - if ($this->stream->test(Twig_Token::OPERATOR_TYPE, ')') || - $this->stream->test(Twig_Token::VAR_END_TYPE) || - $this->stream->test(Twig_Token::BLOCK_END_TYPE) || - $this->stream->test('in')) - break; - $targets[] = $this->parsePrimaryExpression(true); - if (!$this->stream->test(Twig_Token::OPERATOR_TYPE, ',')) - break; - $is_multitarget = true; - } - if (!$is_multitarget && count($targets) == 1) - return array(false, $targets[0]); - return array(true, $targets); - } - - public function subparse($test, $drop_needle=false) - { - $lineno = $this->stream->current->lineno; - $rv = array(); - while (!$this->stream->eof) { - switch ($this->stream->current->type) { - case Twig_Token::TEXT_TYPE: - $token = $this->stream->next(); - $rv[] = new Twig_Text($token->value, $token->lineno); - break; - case Twig_Token::VAR_START_TYPE: - $token = $this->stream->next(); - $expr = $this->parseExpression(); - $this->stream->expect(Twig_Token::VAR_END_TYPE); - $rv[] = new Twig_Print($expr, $token->lineno); - break; - case Twig_Token::BLOCK_START_TYPE: - $this->stream->next(); - $token = $this->stream->current; - if ($token->type !== Twig_Token::NAME_TYPE) - throw new Twig_SyntaxError('expected directive', - $token->lineno); - if (!is_null($test) && call_user_func($test, $token)) { - if ($drop_needle) - $this->stream->next(); - return Twig_NodeList::fromArray($rv, $lineno); - } - if (!isset($this->handlers[$token->value])) - throw new Twig_SyntaxError('unknown directive', - $token->lineno); - $this->stream->next(); - $node = call_user_func($this->handlers[$token->value], - $token); - if (!is_null($node)) - $rv[] = $node; - break; - default: - assert(false, 'Lexer or parser ended up in ' . - 'unsupported state.'); - } - } - - return Twig_NodeList::fromArray($rv, $lineno); - } - - public function parse() - { - try { - $body = $this->subparse(NULL); - } - catch (Twig_SyntaxError $e) { - if (is_null($e->filename)) - $e->filename = $this->stream->filename; - throw $e; - } - if (!is_null($this->extends)) - foreach ($this->blocks as $block) - $block->parent = $this->extends; - return new Twig_Module($body, $this->extends, $this->blocks, - $this->stream->filename); - } -} diff --git a/News/includes/class/Twig/runtime.php b/News/includes/class/Twig/runtime.php deleted file mode 100644 index 3ee3baf..0000000 --- a/News/includes/class/Twig/runtime.php +++ /dev/null @@ -1,485 +0,0 @@ - 'twig_date_format_filter', - 'strftime' => 'twig_strftime_format_filter', - 'strtotime' => 'strtotime', - 'numberformat' => 'number_format', - 'moneyformat' => 'money_format', - 'filesizeformat' => 'twig_filesize_format_filter', - 'format' => 'sprintf', - 'relative' => 'relative_time', - - // numbers - 'even' => 'twig_is_even_filter', - 'odd' => 'twig_is_odd_filter', - - // escaping and encoding - 'escape' => 'twig_escape_filter', - 'e' => 'twig_escape_filter', - 'urlencode' => 'twig_urlencode_filter', - 'quotes' => 'twig_quotes_filter', - 'slashes' => 'addslashes', - - // string filters - 'title' => 'twig_title_string_filter', - 'capitalize' => 'twig_capitalize_string_filter', - 'upper' => 'strtoupper', - 'lower' => 'strtolower', - 'strip' => 'trim', - 'rstrip' => 'rtrim', - 'lstrip' => 'ltrim', - 'translate' => 'twig_translate_string_filter', - 'translate_plural' => 'twig_translate_plural_string_filter', - 'normalize' => 'normalize', - 'truncate' => 'twig_truncate_filter', - 'excerpt' => 'twig_excerpt_filter', - 'replace' => 'twig_replace_filter', - 'match' => 'twig_match_filter', - 'contains' => 'substr_count', - 'linebreaks' => 'nl2br', - 'camelize' => 'camelize', - 'strip_tags' => 'strip_tags', - 'pluralize' => 'twig_pluralize_string_filter', - 'depluralize' => 'twig_depluralize_string_filter', - 'sanitize' => 'sanitize', - 'repeat' => 'str_repeat', - - // array helpers - 'join' => 'twig_join_filter', - 'split' => 'twig_split_filter', - 'first' => 'twig_first_filter', - 'offset' => 'twig_offset_filter', - 'last' => 'twig_last_filter', - 'reverse' => 'array_reverse', - 'length' => 'twig_length_filter', - 'count' => 'count', - 'sort' => 'twig_sort_filter', - - // iteration and runtime - 'default' => 'twig_default_filter', - 'keys' => 'array_keys', - 'items' => 'twig_get_array_items_filter', - - // debugging - 'inspect' => 'twig_inspect_filter', - - 'uploaded' => 'uploaded', - 'fallback' => 'oneof', - 'selected' => 'twig_selected_filter', - 'checked' => 'twig_checked_filter', - 'option_selected' => 'twig_option_selected_filter' -); - - -class Twig_LoopContextIterator implements Iterator -{ - public $context; - public $seq; - public $idx; - public $length; - public $parent; - - public function __construct(&$context, $seq, $parent) - { - $this->context = $context; - $this->seq = $seq; - $this->idx = 0; - $this->length = count($seq); - $this->parent = $parent; - } - - public function rewind() {} - - public function key() {} - - public function valid() - { - return $this->idx < $this->length; - } - - public function next() - { - $this->idx++; - } - - public function current() - { - return $this; - } -} - -function unretarded_array_unshift(&$arr, &$val) { - $arr = array_merge(array(&$val), $arr); -} - -/** - * This is called like an ordinary filter just with the name of the filter - * as first argument. Currently we just raise an exception here but it - * would make sense in the future to allow dynamic filter lookup for plugins - * or something like that. - */ -function twig_missing_filter($name) -{ - $args = func_get_args(); - array_shift($args); - - $text = $args[0]; - array_shift($args); - - array_unshift($args, $name); - unretarded_array_unshift($args, $text); - - $trigger = Trigger::current(); - - if ($trigger->exists($name)) - return call_user_func_array(array($trigger, "filter"), $args); - - return $text; -} - -function twig_get_attribute($obj, $item, $function = true) -{ - if (is_array($obj) && isset($obj[$item])) - return $obj[$item]; - if (!is_object($obj)) - return NULL; - if ($function and method_exists($obj, $item)) - return call_user_func(array($obj, $item)); - if (property_exists($obj, $item)) { - $tmp = get_object_vars($obj); - return $tmp[$item]; - } - $method = 'get' . ucfirst($item); - if ($function and method_exists($obj, $method)) - return call_user_func(array($obj, $method)); - if (is_object($obj)) { - @$obj->$item; # Funky way of allowing __get to activate before returning the value. - return @$obj->$item; - } - return NULL; -} - -function twig_paginate(&$context, $as, $over, $per_page) -{ - $name = (in_array("page", Paginator::$names)) ? $as."_page" : "page" ; - - if (count($over) == 2 and $over[0] instanceof Model and is_string($over[1])) - $context[$as] = $context["::parent"][$as] = new Paginator($over[0]->__getPlaceholders($over[1]), $per_page, $name); - else - $context[$as] = $context["::parent"][$as] = new Paginator($over, $per_page, $name); -} - -function twig_iterate(&$context, $seq) -{ - $parent = isset($context['loop']) ? $context['loop'] : null; - $seq = twig_make_array($seq); - $context['loop'] = array('parent' => $parent, 'iterated' => false); - return new Twig_LoopContextIterator($context, $seq, $parent); -} - -function twig_set_loop_context(&$context, $iterator, $target) -{ - $context[$target] = $iterator->seq[$iterator->idx]; - $context['loop'] = twig_make_loop_context($iterator); -} - -function twig_set_loop_context_multitarget(&$context, $iterator, $targets) -{ - $values = $iterator->seq[$iterator->idx]; - if (!is_array($values)) - $values = array($values); - $idx = 0; - foreach ($values as $value) { - if (!isset($targets[$idx])) - break; - $context[$targets[$idx++]] = $value; - } - $context['loop'] = twig_make_loop_context($iterator); -} - -function twig_make_loop_context($iterator) -{ - return array( - 'parent' => $iterator->parent, - 'length' => $iterator->length, - 'index0' => $iterator->idx, - 'index' => $iterator->idx + 1, - 'revindex0' => $iterator->length - $iterator->idx - 1, - 'revindex '=> $iterator->length - $iterator->idx, - 'first' => $iterator->idx == 0, - 'last' => $iterator->idx + 1 == $iterator->length, - 'iterated' => true - ); -} - -function twig_make_array($object) -{ - if (is_array($object)) - return array_values($object); - elseif (is_object($object)) { - $result = array(); - foreach ($object as $value) - $result[] = $value; - return $result; - } - return array(); -} - -function twig_date_format_filter($timestamp, $format='F j, Y, G:i') -{ - return when($format, $timestamp); -} - -function twig_strftime_format_filter($timestamp, $format='%x %X') -{ - return when($format, $timestamp, true); -} - -function twig_urlencode_filter($url, $raw=false) -{ - if ($raw) - return rawurlencode($url); - return urlencode($url); -} - -function twig_join_filter($value, $glue='') -{ - return implode($glue, (array) $value); -} - -function twig_default_filter($value, $default='') -{ - return is_null($value) ? $default : $value; -} - -function twig_get_array_items_filter($array) -{ - $result = array(); - foreach ($array as $key => $value) - $result[] = array($key, $value); - return $result; -} - -function twig_filesize_format_filter($value) -{ - $value = max(0, (int)$value); - $places = strlen($value); - if ($places <= 9 && $places >= 7) { - $value = number_format($value / 1048576, 1); - return "$value MB"; - } - if ($places >= 10) { - $value = number_format($value / 1073741824, 1); - return "$value GB"; - } - $value = number_format($value / 1024, 1); - return "$value KB"; -} - -function twig_is_even_filter($value) -{ - return $value % 2 == 0; -} - -function twig_is_odd_filter($value) -{ - return $value % 2 == 1; -} - -function twig_replace_filter($str, $search, $replace, $regex = false) -{ - if ($regex) - return preg_replace($search, $replace, $str); - else - return str_replace($search, $replace, $str); -} - -function twig_match_filter($str, $match) -{ - return preg_match($match, $str); -} - - -// add multibyte extensions if possible -if (function_exists('mb_get_info')) { - function twig_upper_filter($string) - { - $template = twig_get_current_template(); - if (!is_null($template->charset)) - return mb_strtoupper($string, $template->charset); - return strtoupper($string); - } - - function twig_lower_filter($string) - { - $template = twig_get_current_template(); - if (!is_null($template->charset)) - return mb_strtolower($string, $template->charset); - return strtolower($string); - } - - function twig_title_string_filter($string) - { - $template = twig_get_current_template(); - if (is_null($template->charset)) - return ucwords(strtolower($string)); - return mb_convert_case($string, MB_CASE_TITLE, $template->charset); - } - - function twig_capitalize_string_filter($string) - { - $template = twig_get_current_template(); - if (is_null($template->charset)) - return ucfirst(strtolower($string)); - return mb_strtoupper(mb_substr($string, 0, 1, $template->charset)) . - mb_strtolower(mb_substr($string, 1, null, $template->charset)); - } - - // override the builtins - $twig_filters['upper'] = 'twig_upper_filter'; - $twig_filters['lower'] = 'twig_lower_filter'; -} - -// and byte fallback -else { - function twig_title_string_filter($string) - { - return ucwords(strtolower($string)); - } - - function twig_capitalize_string_filter($string) - { - return ucfirst(strtolower($string)); - } -} - -function twig_translate_string_filter($string, $domain = "theme") { - $domain = ($domain == "theme" and ADMIN) ? "chyrp" : $domain ; - return __($string, $domain); -} - -function twig_translate_plural_string_filter($single, $plural, $number, $domain = "theme") { - $domain = ($domain == "theme" and ADMIN) ? "chyrp" : $domain ; - return _p($single, $plural, $number, $domain); -} - -function twig_inspect_filter($thing) { - if (ini_get("xdebug.var_display_max_depth") == -1) - return var_dump($thing); - else - return '
' .
-               fix(var_export($thing, true)) .
-               '
'; -} - -function twig_split_filter($string, $cut = " ") { - return explode($cut, $string); -} - -function twig_first_filter($array) { - foreach ($array as $key => &$val) - return $val; # Return the first one. - - return false; -} - -function twig_last_filter($array) { - return $array[count($array) - 1]; -} - -function twig_offset_filter($array, $offset = 0) { - return $array[$offset]; -} - -function twig_selected_filter($foo) { - $try = func_get_args(); - array_shift($try); - - $just_class = (end($try) === true); - if ($just_class) - array_pop($try); - - if (is_array($try[0])) { - foreach ($try as $index => $it) - if ($index) - $try[0][] = $it; - - $try = $try[0]; - } - - if (in_array($foo, $try)) - return ($just_class) ? " selected" : ' class="selected"' ; -} - -function twig_checked_filter($foo) { - if ($foo) - return ' checked="checked"'; -} - -function twig_option_selected_filter($foo) { - $try = func_get_args(); - array_shift($try); - - if (in_array($foo, $try)) - return ' selected="selected"'; -} - -function twig_pluralize_string_filter($string, $number = null) { - if ($number and $number == 1) - return $string; - else - return pluralize($string); -} - -function twig_depluralize_string_filter($string) { - return depluralize($string); -} - -function twig_quotes_filter($string) { - return str_replace(array('"', "'"), array('\"', "\\'"), $string); -} - -function twig_length_filter($thing) { - if (is_string($thing)) - return strlen($thing); - else - return count($thing); -} - -function twig_escape_filter($string, $quotes = true, $decode = true) { - if (!is_string($string)) # Certain post attributes might be parsed from YAML to an array, - return $string; # in which case the module provides a value. However, the attr - # is still passed to the "fallback" and "fix" filters when editing. - - $safe = fix($string, $quotes); - return $decode ? preg_replace("/&(#?[A-Za-z0-9]+);/", "&\\1;", $safe) : $safe ; -} - -function twig_truncate_filter($text, $length = 100, $ending = "...", $exact = false, $html = true) { - return truncate($text, $length, $ending, $exact, $html); -} - -function twig_excerpt_filter($text, $length = 200, $ending = "...", $exact = false, $html = true) { - $paragraphs = preg_split("/(\r?\n\r?\n|\r\r)/", $text); - if (count($paragraphs) > 1) - return $paragraphs[0]; - else - return truncate($text, $length, $ending, $exact, $html); -} - -function twig_sort_filter($array) { - asort($array); - return $array; -} diff --git a/News/includes/class/Twig/spec.html b/News/includes/class/Twig/spec.html deleted file mode 100644 index db10e70..0000000 --- a/News/includes/class/Twig/spec.html +++ /dev/null @@ -1,807 +0,0 @@ - - - - - - -Twig Template Engine Specification - - - -
-

Twig Template Engine Specification

-

This specification specifies a simple cross-language template engine for at least -PHP, Python and Ruby.

-
-

Purpose

-

A language independent and simple template engine is useful for applications that -use code which is written in more than one programming language. Good Examples -are portal systems which use a blog written in Ruby, a forum software written in -PHP and a planet system written in Python.

-
-
-

Inspiration

-

Twig uses a syntax similar to the Genshi text templates which in turn were -inspired by django which also inspired Jinja (all three of them python template -engines) which inspired the Twig runtime environment.

-
-
-

Undefined Behavior

-

To simplify porting the template language to different platforms in a couple of -situations the behavior is undefined. Template authors may never take advantage -of such a situation!

-
-
-

Syntax

-

I'm too lazy to write down the syntax as BNF diagram but the following snippet -should explain the syntax elements:

-
-<!DOCTYPE HTML>
-{# This is a comment #}
-<title>{% block title %}Page Title Goes Here{% endblock %}</title>
-{% if show_navigation %}
-<nav>
-  <ul>
-  {% for item in navigation %}
-    <li><a href="${item.href|e}">$item.caption</a></li>
-  {% endfor %}
-  </ul>
-</nav>
-{% endif %}
-<article>{% block body %}{% endblock %}</article>
-
-
-

Comments and Whitespace

-

Everything between {# and #} is ignored by the lexer. Inside blocks and -variable sections the Lexer has to remove whitespace too.

-
-
-

Output Expressions

-

To output expressions two syntaxes exist. Simple variable output or full -expression output:

-
-$this.is.a.variable.output
-${ expression | goes | here }
-
-

The former is what we call a variable expression, the second a full expression. -Variable expressions must not contain whitespace, whereas a full expression -must print the output of the full wrapped expression.

-
-
-

Expressions

-

Expressions allow basic string manipulation and arithmetic calculations. It is -an infix syntax with the following operators in this precedence:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OperatorDescription
+Convert both arguments into a number and add them up.
-Convert both arguments into a number and substract them.
*Convert both arguments into a number and multiply them.
/Convert both arguments into a number and divide them.
%Convert both arguments into a number and calculate the rest -of the integer division.
~Convert both arguments into a string and concatenate them.
orTrue if the left or the right expression is true.
andTrue if the left and the right expression is true.
notnegate the expression
-
-

All number conversions have an undefined precision but the implementations -should try to select the best possible type. For example, if the implementation -sees an integer and a float that looks like an integer it may convert the -latter into a long and add them.

-

Use parentheses to group expressions.

-

If an object cannot be compared the implementation might raise an error or fail -silently. Template authors may never apply mathematical operators to untrusted -data. This is especially true for the php implementation where the following -outputs 42:

-
-${ "foo41" + 1 }
-
-

This is undefined behavior and will break on different implementations or -return 0 as "foo41" is not a valid number.

-
-

Types

-

The following types exist:

-
- ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeLiteralDescription
integerd+One of the two numeric types. Which of them -is used and when is up to the implementation.
floatd+.d+Floating point values.
stringsee belowA unicode string. The PHP implementation has -to use bytestrings here and may use mb_string.
bool(true|false)Represents boolean values.
nonenoneThis type is returned on missing variables or -attributes.
-
-

String regex:

-
-(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')(?sm)
-
-
-
-

Attribute Lookup

-

There are two ways to look up attributes on objects. The dot and the -subscript syntax, both inspired by JavaScript. Basically the following -expressions do the very same:

-
-foo.name.0
-foo['name'][0]
-
-

This is useful to dynamically get attributes from objects:

-
-foo[bar]
-
-

The underlaying implementation is free to specify on it's own what an attribute -lookup means. The PHP reference implementation for example performs those -actions on foo.bar:

-
    -
  • try $foo['bar']
  • -
  • try $foo->bar()
  • -
  • try $foo->bar
  • -
  • try $foo->getBar()
  • -
-

The first match returns the object, attribute access to nonexisting attributes -returns none.

-
-
-

Filtering

-

The template language does not specify function calls, but filters can be used -to further modify variables using functions the template engine provides.

-

The following snippet shows how filters are translated to function calls:

-
-${ 42 | foo(1, 2) | bar | baz }
-    ->  baz(bar(foo(42, 1, 2)))
-
-

The following filters must be provided by the implementation:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescription
dateFormat the timestamp using the PHP date formatting -rules. This may sound like a nonstandard way of -formatting dates but it's a way very popular among -template designers and also used by django.
strftimeFormat the timestamp using standard strftime rules.
numberformatApply number formatting on the string. This may or -may not use local specific rules.
moneyformatLike numberformat but for money.
filesizeformatTakes a number of bytes and displays it as KB/MB/GB
format
-
Applies sprintf formatting on the string::
-
${ "%s %2f" | format(string, float) }
-
-
evenIs the number even?
oddIs the number odd?
escapeApply HTML escaping on a string. This also has to -convert " to &quot; but leave `' unmodified.
eAlias for escape.
urlencodeURL encode the string. If the second parameter is -true this function should encode for path sections, -otherwise for query strings.
quotesEscape quotes (', ", etc.)
titleMake the string lowercase and upper case the first -characters of all words.
capitalizeLike title but capitalizes only the first char of -the whole string.
upperConvert the string to uppercase.
lowerConvert the string to lowercase.
stripTrim leading and trailing whitespace.
lstripTrim leading whitespace.
rstripTrim trailing whitespace.
translateTranslate the string using either the "theme" domain -or the "chyrp" domain if in Admin. (Chyrp-specific)
translate_pluralTranslate the (singular) string, or the plural string -if the number passed is not 1.
normalizeConvert all excessive whitespace (including linebreaks) -into a single space.
truncateTruncate a string, providing ellipsis, if it is longer -than the passed length. Keeps words in tact by default, -but with a second boolean parameter will be strict.
replaceReplaces the occurrence of the first argument with the -second argument in the string.
linebreaksConvert linebreaks to <br />'s.
camelizeConvert string to camelcase.
strip_tagsStrip HTML from the string.
pluralizeReturn the pluralization of a string, or if a number -is passed and it is 1, don't pluralize.
sanitizeRemove special characters from a string.
joinConcatenate the array items and join them with the -string provided (or commas by default).
splitSplit a string into an array at the given breakpoints.
firstFirst entry of an Array.
offsetEntry at Array[offset].
lastLast entry of an Array.
reverseReverse the Array items.
countCount the number of items in an array or string -characters.
lengthAlias for count.
defaultIf the value is none the first argument is returned
keysKeys of an Array.
itemsItems of an Array.
inspectDumps the variable or value.
fallbackIf the value is empty or none, return this value.
selectedIf the first argument is the same as the value, output -class="selected", or selected if the second -argument is true.
option_selectedSame as selected, but for selected="selected".
checkedSame as selected, but for checked="checked".
-
-

Additionally, if a filter is missing (say, ${ foo | bar_filter }, in Chyrp it -checks for an associated Trigger filter by that filter's name.

-
-
-
-

For Loops

-

Iteration works via for loops. Loops work a bit like their Python counterparts, -except that they don't support multilevel tuple unpacking and that they add a new -layer to the context. Thus at the end of the iteration all the modifications on -the context disappear. Additionally, inside loops you have access to a special -loop object which provides runtime information:

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VariableDescription
loop.indexThe current iteration of the loop (1-indexed)
loop.index0The current iteration of the loop (0-indexed)
loop.revindexThe number of iterations from the end of the -loop (1-indexed)
loop.revindex0The number of iterations from the end of the -loop (0-indexed)
loop.firstTrue if this is the first time through the loop
loop.lastTrue if this is the last time through the loop
loop.parentFor nested loops, this is the loop "above" the -current one
-
-

Additionally for loops can have an else section that is executed if no -iteration took place.

-
-

Example

-
-<ul>
-{% for user in users %}
-    <li><a href="$user.href">${ user.username | escape }</a></li>
-{% else %}
-    <li><em>No users found!</em></li>
-{% endfor %}
-</ul>
-
-
-
-

Notes on Iteration

-

Because we have to cope with PHP too, which has problematic arrays that are -neither hashmaps nor lists, we have no support for associative array iteration -at all. How do you iterate over associative arrays then? Using a filter:

-
-{% for key, value in array | items %}
-    ...
-{% endfor %}
-
-

To iterate over the keys only:

-
-{% for key in array | keys %}
-    ...
-{% endfor %}
-
-
-
-
-

If Conditions

-

If conditions work like like Ruby, PHP and Python, just that we use PHP -keywords. Also, use elseif and not else if:

-
-{% if expr1 %}
-    ...
-{% elseif expr2 %}
-    ...
-{% else %}
-    ...
-{% endif %}
-
-
-
-

Inheritance

-

Template inheritance allows you to build a base "skeleton" template that -contains all the common elements of your site and defines blocks that -child templates can override.

-

Here a small template inheritance example:

-
-<!DOCTYPE HTML>
-<html lang="en">
-  <link rel="stylesheet" href="style.css">
-  <title>{% block title %}My site{% endblock %}</title>
-  <div id="sidebar">
-    {% block sidebar %}
-     <ul>
-        <li><a href="/">Home</a></li>
-        <li><a href="/blog/">Blog</a></li>
-     </ul>
-     {% endblock %}
-  </div>
-  <div id="content">
-     {% block content %}{% endblock %}
-  </div>
-</html>
-
-

If we call that template "base.html" a "index.html" template could override -it and fill in the blocks:

-
-{% extends "base.html" %}
-{% block title %}Foo &mdash; {% super %}{% endblock %}
-{% block content %}
-    This is the content
-{% endblock %}
-
-

By using {% super %} you can render the parent's block. The template -filenames must be constant strings (we don't support dynamic inheritance -for simplicity) and are relative to the loader folder, not the current -template.

-
-
-
- - diff --git a/News/includes/class/Twig/spec.txt b/News/includes/class/Twig/spec.txt deleted file mode 100644 index 878133c..0000000 --- a/News/includes/class/Twig/spec.txt +++ /dev/null @@ -1,363 +0,0 @@ -================================== -Twig Template Engine Specification -================================== - - -This specification specifies a simple cross-language template engine for at least -PHP, Python and Ruby. - - -Purpose -======= - -A language independent and simple template engine is useful for applications that -use code which is written in more than one programming language. Good Examples -are portal systems which use a blog written in Ruby, a forum software written in -PHP and a planet system written in Python. - - -Inspiration -=========== - -Twig uses a syntax similar to the Genshi text templates which in turn were -inspired by django which also inspired Jinja (all three of them python template -engines) which inspired the Twig runtime environment. - - -Undefined Behavior -================== - -To simplify porting the template language to different platforms in a couple of -situations the behavior is undefined. Template authors may never take advantage -of such a situation! - - -Syntax -====== - -I'm too lazy to write down the syntax as BNF diagram but the following snippet -should explain the syntax elements:: - - - {# This is a comment #} - {% block title %}Page Title Goes Here{% endblock %} - {% if show_navigation %} - - {% endif %} -
{% block body %}{% endblock %}
- - -Comments and Whitespace ------------------------ - -Everything between ``{#`` and ``#}`` is ignored by the lexer. Inside blocks and -variable sections the Lexer has to remove whitespace too. - - -Output Expressions ------------------- - -To output expressions two syntaxes exist. Simple variable output or full -expression output:: - - $this.is.a.variable.output - ${ expression | goes | here } - -The former is what we call a variable expression, the second a full expression. -Variable expressions must not contain whitespace, whereas a full expression -must print the output of the full wrapped expression. - - -Expressions ------------ - -Expressions allow basic string manipulation and arithmetic calculations. It is -an infix syntax with the following operators in this precedence: - - =========== ============================================================== - Operator Description - =========== ============================================================== - ``+`` Convert both arguments into a number and add them up. - ``-`` Convert both arguments into a number and substract them. - ``*`` Convert both arguments into a number and multiply them. - ``/`` Convert both arguments into a number and divide them. - ``%`` Convert both arguments into a number and calculate the rest - of the integer division. - ``~`` Convert both arguments into a string and concatenate them. - ``or`` True if the left or the right expression is true. - ``and`` True if the left and the right expression is true. - ``not`` negate the expression - =========== ============================================================== - -All number conversions have an undefined precision but the implementations -should try to select the best possible type. For example, if the implementation -sees an integer and a float that looks like an integer it may convert the -latter into a long and add them. - -Use parentheses to group expressions. - -If an object cannot be compared the implementation might raise an error or fail -silently. Template authors may never apply mathematical operators to untrusted -data. This is especially true for the php implementation where the following -outputs ``42``:: - - ${ "foo41" + 1 } - -This is undefined behavior and will break on different implementations or -return ``0`` as ``"foo41"`` is not a valid number. - -Types -~~~~~ - -The following types exist: - - =========== =============== ============================================== - Type Literal Description - =========== =============== ============================================== - ``integer`` `\d+` One of the two numeric types. Which of them - is used and when is up to the implementation. - ``float`` `\d+\.\d+` Floating point values. - ``string`` see below A unicode string. The PHP implementation has - to use bytestrings here and may use mb_string. - ``bool`` `(true|false)` Represents boolean values. - ``none`` `none` This type is returned on missing variables or - attributes. - =========== =============== ============================================== - -String regex:: - - (?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')(?sm) - -Attribute Lookup -~~~~~~~~~~~~~~~~ - -There are two ways to look up attributes on objects. The dot and the -subscript syntax, both inspired by JavaScript. Basically the following -expressions do the very same:: - - foo.name.0 - foo['name'][0] - -This is useful to dynamically get attributes from objects:: - - foo[bar] - -The underlaying implementation is free to specify on it's own what an attribute -lookup means. The PHP reference implementation for example performs these -actions on ``foo.bar``: - -- try ``$foo['bar']`` -- try ``$foo->bar()`` (if they're using ``foo.bar`` and not ``foo[bar]``) -- try ``$foo->bar`` -- try ``$foo->getBar()`` (if they're using ``foo.bar`` and not ``foo[bar]``) - -The first match returns the object, attribute access to nonexisting attributes -returns `none`. - -Filtering -~~~~~~~~~ - -The template language does not specify function calls, but filters can be used -to further modify variables using functions the template engine provides. - -The following snippet shows how filters are translated to function calls:: - - ${ 42 | foo(1, 2) | bar | baz } - -> baz(bar(foo(42, 1, 2))) - -The following filters must be provided by the implementation: - - =================== ====================================================== - Name Description - =================== ====================================================== - `date` Format the timestamp using the PHP date formatting - rules. This may sound like a nonstandard way of - formatting dates but it's a way very popular among - template designers and also used by django. - `strftime` Format the timestamp using standard strftime rules. - `numberformat` Apply number formatting on the string. This may or - may not use local specific rules. - `moneyformat` Like `numberformat` but for money. - `filesizeformat` Takes a number of bytes and displays it as KB/MB/GB - `format` Applies `sprintf` formatting on the string:: - ${ "%s %2f" | format(string, float) } - `even` Is the number even? - `odd` Is the number odd? - `escape` Apply HTML escaping on a string. This also has to - convert `"` to `" but leave `'` unmodified. - `e` Alias for `escape`. - `urlencode` URL encode the string. If the second parameter is - true this function should encode for path sections, - otherwise for query strings. - `quotes` Escape quotes (\', \", etc.) - `title` Make the string lowercase and upper case the first - characters of all words. - `capitalize` Like `title` but capitalizes only the first char of - the whole string. - `upper` Convert the string to uppercase. - `lower` Convert the string to lowercase. - `strip` Trim leading and trailing whitespace. - `lstrip` Trim leading whitespace. - `rstrip` Trim trailing whitespace. - `translate` Translate the string using either the "theme" domain - or the "chyrp" domain if in Admin. (Chyrp-specific) - `translate_plural` Translate the (singular) string, or the plural string - if the number passed is not 1. - `normalize` Convert all excessive whitespace (including linebreaks) - into a single space. - `truncate` Truncate a string, providing ellipsis, if it is longer - than the passed length. Keeps words in tact by default, - but with a second boolean parameter will be strict. - `replace` Replaces the occurrence of the first argument with the - second argument in the string. - `linebreaks` Convert linebreaks to
's. - `camelize` Convert string to camelcase. - `strip_tags` Strip HTML from the string. - `pluralize` Return the pluralization of a string, or if a number - is passed and it is 1, don't pluralize. - `sanitize` Remove special characters from a string. - `join` Concatenate the array items and join them with the - string provided (or commas by default). - `split` Split a string into an array at the given breakpoints. - `first` First entry of an Array. - `offset` Entry at Array[offset]. - `last` Last entry of an Array. - `reverse` Reverse the Array items. - `count` Count the number of items in an array or string - characters. - `length` Alias for `count`. - `default` If the value is `none` the first argument is returned - `keys` Keys of an Array. - `items` Items of an Array. - `inspect` Dumps the variable or value. - `fallback` If the value is empty or `none`, return this value. - `selected` If the first argument is the same as the value, output - `class="selected"`, or `selected` if the second - argument is `true`. - `option_selected` Same as `selected`, but for `selected="selected"`. - `checked` Same as `selected`, but for `checked="checked"`. - =================== ====================================================== - -Additionally, if a filter is missing (say, ${ foo | bar_filter }, in Chyrp it -checks for an associated Trigger filter by that filter's name. - - -For Loops ---------- - -Iteration works via for loops. Loops work a bit like their Python counterparts, -except that they don't support multilevel tuple unpacking and that they add a new -layer to the context. Thus at the end of the iteration all the modifications on -the context disappear. Additionally, inside loops you have access to a special -`loop` object which provides runtime information: - - ====================== =================================================== - Variable Description - ====================== =================================================== - ``loop.index`` The current iteration of the loop (1-indexed) - ``loop.index0`` The current iteration of the loop (0-indexed) - ``loop.revindex`` The number of iterations from the end of the - loop (1-indexed) - ``loop.revindex0`` The number of iterations from the end of the - loop (0-indexed) - ``loop.first`` True if this is the first time through the loop - ``loop.last`` True if this is the last time through the loop - ``loop.parent`` For nested loops, this is the loop "above" the - current one - ====================== =================================================== - -Additionally for loops can have an `else` section that is executed if no -iteration took place. - -Example -~~~~~~~ - -:: - - - - -Notes on Iteration -~~~~~~~~~~~~~~~~~~ - -Because we have to cope with PHP too, which has problematic arrays that are -neither hashmaps nor lists, we have no support for associative array iteration -at all. How do you iterate over associative arrays then? Using a filter:: - - {% for key, value in array | items %} - ... - {% endfor %} - -To iterate over the keys only:: - - {% for key in array | keys %} - ... - {% endfor %} - - -If Conditions -------------- - -If conditions work like like Ruby, PHP and Python, just that we use PHP -keywords. Also, use `elseif` and not `else if`:: - - {% if expr1 %} - ... - {% elseif expr2 %} - ... - {% else %} - ... - {% endif %} - - -Inheritance ------------ - -Template inheritance allows you to build a base "skeleton" template that -contains all the common elements of your site and defines **blocks** that -child templates can override. - -Here a small template inheritance example:: - - - - - {% block title %}My site{% endblock %} - -
- {% block content %}{% endblock %} -
- - -If we call that template "base.html" a "index.html" template could override -it and fill in the blocks:: - - {% extends "base.html" %} - {% block title %}Foo — {% super %}{% endblock %} - {% block content %} - This is the content - {% endblock %} - -By using `{% super %}` you can render the parent's block. The template -filenames must be constant strings (we don't support dynamic inheritance -for simplicity) and are relative to the loader folder, not the current -template. diff --git a/News/includes/close.png b/News/includes/close.png deleted file mode 100755 index 8d42fec..0000000 Binary files a/News/includes/close.png and /dev/null differ diff --git a/News/includes/common.php b/News/includes/common.php deleted file mode 100755 index 9ad37d9..0000000 --- a/News/includes/common.php +++ /dev/null @@ -1,307 +0,0 @@ - - require_once INCLUDES_DIR."/class/Config.php"; - - # File: SQL - # See Also: - # - require_once INCLUDES_DIR."/class/SQL.php"; - - # File: Model - # See Also: - # - require_once INCLUDES_DIR."/class/Model.php"; - - # File: User - # See Also: - # - require_once INCLUDES_DIR."/model/User.php"; - - # File: Visitor - # See Also: - # - require_once INCLUDES_DIR."/model/Visitor.php"; - - # File: Post - # See Also: - # - require_once INCLUDES_DIR."/model/Post.php"; - - # File: Page - # See Also: - # - require_once INCLUDES_DIR."/model/Page.php"; - - # File: Group - # See Also: - # - require_once INCLUDES_DIR."/model/Group.php"; - - # File: Session - # See Also: - # - require_once INCLUDES_DIR."/class/Session.php"; - - # File: Flash - # See Also: - # - require_once INCLUDES_DIR."/class/Flash.php"; - - # File: Theme - # See Also: - # - require_once INCLUDES_DIR."/class/Theme.php"; - - # File: Trigger - # See Also: - # - require_once INCLUDES_DIR."/class/Trigger.php"; - - # File: Module - # See Also: - # - require_once INCLUDES_DIR."/class/Modules.php"; - - # File: Feathers - # See Also: - # - require_once INCLUDES_DIR."/class/Feathers.php"; - - # File: Paginator - # See Also: - # - require_once INCLUDES_DIR."/class/Paginator.php"; - - # File: Twig - # Chyrp's templating engine. - require_once INCLUDES_DIR."/class/Twig.php"; - - # File: Route - # See Also: - # - require_once INCLUDES_DIR."/class/Route.php"; - - # File: Main - # See Also: - #
- require_once INCLUDES_DIR."/controller/Main.php"; - - # File: Admin - # See Also: - # - require_once INCLUDES_DIR."/controller/Admin.php"; - - # File: Feather - # See Also: - # - require_once INCLUDES_DIR."/interface/Feather.php"; - - # Set the error handler to exit on error if this is being run from the tester. - if (TESTER) - set_error_handler("error_panicker"); - - # Redirect to the installer if there is no config. - if (!file_exists(INCLUDES_DIR."/config.yaml.php")) - redirect("install.php"); - - # Start the timer that keeps track of Chyrp's load time. - timer_start(); - - # Load the config settings. - $config = Config::current(); - - # Prepare the SQL interface. - $sql = SQL::current(); - - # Set the timezone for date(), etc. - set_timezone($config->timezone); - - # Initialize connection to SQL server. - $sql->connect(); - - # Sanitize all input depending on magic_quotes_gpc's enabled status. - sanitize_input($_GET); - sanitize_input($_POST); - sanitize_input($_COOKIE); - sanitize_input($_REQUEST); - - # Begin the session. - session(); - - # Set the locale for gettext. - set_locale($config->locale); - - # Load the translation engine. - load_translator("chyrp", INCLUDES_DIR."/locale/".$config->locale.".mo"); - - # Constant: PREVIEWING - # Is the user previewing a theme? - define('PREVIEWING', !ADMIN and !empty($_SESSION['theme'])); - - # Constant: THEME_DIR - # Absolute path to /themes/(current/previewed theme) - define('THEME_DIR', MAIN_DIR."/themes/".(PREVIEWING ? $_SESSION['theme'] : $config->theme)); - - # Constant: THEME_URL - # URL to /themes/(current/previewed theme) - define('THEME_URL', $config->chyrp_url."/themes/".(PREVIEWING ? $_SESSION['theme'] : $config->theme)); - - # Initialize the theme. - $theme = Theme::current(); - - # Load the Visitor. - $visitor = Visitor::current(); - - # Prepare the notifier. - $flash = Flash::current(); - - # Initiate the extensions. - init_extensions(); - - # Prepare the trigger class - $trigger = Trigger::current(); - - # Filter the visitor immediately after the Modules are initialized. - # Example usage scenario: custom auth systems (e.g. OpenID) - $trigger->filter($visitor, "visitor"); - - # First general-purpose trigger. There are many cases you may want to use @route_init@ instead of this, however. - $trigger->call("runtime"); - - # Set the content-type to the theme's "type" setting, or "text/html". - header("Content-type: ".(INDEX ? fallback($theme->type, "text/html") : "text/html")."; charset=UTF-8"); diff --git a/News/includes/controller/Admin.php b/News/includes/controller/Admin.php deleted file mode 100755 index bba44cb..0000000 --- a/News/includes/controller/Admin.php +++ /dev/null @@ -1,2442 +0,0 @@ -admin_theme = fallback($_SESSION['admin_theme'], "default"); - - $this->theme = new Twig_Loader(MAIN_DIR."/admin/themes/".$this->admin_theme, - (is_writable(INCLUDES_DIR."/caches") and !DEBUG) ? - INCLUDES_DIR."/caches" : - null); - - $this->default = new Twig_Loader(MAIN_DIR."/admin/themes/default", - (is_writable(INCLUDES_DIR."/caches") and !DEBUG) ? - INCLUDES_DIR."/caches" : - null); - } - - /** - * Function: parse - * Determines the action. - */ - public function parse($route) { - $visitor = Visitor::current(); - - # Protect non-responder functions. - if (in_array($route->action, array("__construct", "parse", "subnav_context", "display", "current"))) - show_404(); - - if (empty($route->action) or $route->action == "write") { - # "Write > Post", if they can add posts or drafts. - if (($visitor->group->can("add_post") or $visitor->group->can("add_draft")) and - !empty(Config::current()->enabled_feathers)) - return $route->action = "write_post"; - - # "Write > Page", if they can add pages. - if ($visitor->group->can("add_page")) - return $route->action = "write_page"; - } - - if (empty($route->action) or $route->action == "manage") { - # "Manage > Posts", if they can manage any posts. - if (Post::any_editable() or Post::any_deletable()) - return $route->action = "manage_posts"; - - # "Manage > Pages", if they can manage pages. - if ($visitor->group->can("edit_page") or $visitor->group->can("delete_page")) - return $route->action = "manage_pages"; - - # "Manage > Users", if they can manage users. - if ($visitor->group->can("edit_user") or $visitor->group->can("delete_user")) - return $route->action = "manage_users"; - - # "Manage > Groups", if they can manage groups. - if ($visitor->group->can("edit_group") or $visitor->group->can("delete_group")) - return $route->action = "manage_groups"; - } - - if (empty($route->action) or $route->action == "settings") { - # "General Settings", if they can configure the installation. - if ($visitor->group->can("change_settings")) - return $route->action = "general_settings"; - } - - if (empty($route->action) or $route->action == "extend") { - # "Modules", if they can configure the installation. - if ($visitor->group->can("toggle_extensions")) - return $route->action = "modules"; - } - - Trigger::current()->filter($route->action, "admin_determine_action"); - - if (!isset($route->action)) - show_403(__("Access Denied"), __("You do not have sufficient privileges to view this area.")); - } - - /** - * Function: write - * Post writing. - */ - public function write_post() { - $visitor = Visitor::current(); - - if (!$visitor->group->can("add_post", "add_draft")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create posts.")); - - $config = Config::current(); - - if (empty($config->enabled_feathers)) - error(__("No Feathers"), __("Please install a feather or two in order to add a post.")); - - Trigger::current()->filter($options, array("write_post_options", "post_options")); - - fallback($_GET['feather'], reset($config->enabled_feathers)); - - $this->display("write_post", - array("groups" => Group::find(array("order" => "id ASC")), - "options" => $options, - "feathers" => Feathers::$instances, - "feather" => Feathers::$instances[$_GET['feather']])); - } - - /** - * Function: bookmarklet - * Post writing, from the bookmarklet. - */ - public function bookmarklet() { - $visitor = Visitor::current(); - if (!$visitor->group->can("add_post", "add_draft")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create posts.")); - - $config = Config::current(); - - if (empty($config->enabled_feathers)) - error(__("No Feathers"), __("Please install a feather or two in order to add a post.")); - - if (!isset($this->selected_bookmarklet)) - fallback($feather, $config->enabled_feathers[0]); - else - $feather = $this->selected_bookmarklet; - - fallback($_GET['url']); - fallback($_GET['title']); - fallback($_GET['selection']); - - $this->display("bookmarklet", - array("done" => isset($_GET['done']), - "feathers" => Feathers::$instances, - "selected_feather" => Feathers::$instances[$feather], - "args" => array("url" => stripslashes($_GET['url']), - "page_url" => stripslashes($_GET['url']), - "page_link" => '(via '.$_GET['title'].')', - "title" => stripslashes($_GET['title']), - "page_title" => stripslashes($_GET['title']), - "selection" => stripslashes($_GET['selection'])))); - } - - /** - * Function: add_post - * Adds a post when the form is submitted. - */ - public function add_post() { - $visitor = Visitor::current(); - if (!$visitor->group->can("add_post", "add_draft")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create posts.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - if (!isset($_POST['draft']) and !$visitor->group->can("add_post")) - $_POST['draft'] = 'true'; - - $post = Feathers::$instances[$_POST['feather']]->submit(); - - if (!$post->redirect) - $post->redirect = "/admin/?action=write_post"; - - if (!isset($_POST['bookmarklet'])) - Flash::notice(__("Post created!"), $post->redirect); - else - redirect($post->redirect); - } - - /** - * Function: edit_post - * Post editing. - */ - public function edit_post() { - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to edit a post.")); - - $post = new Post($_GET['id'], array("drafts" => true, "filter" => false)); - - if (!$post->editable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this post.")); - - Trigger::current()->filter($options, array("edit_post_options", "post_options"), $post); - - $this->display("edit_post", - array("post" => $post, - "groups" => Group::find(array("order" => "id ASC")), - "options" => $options, - "feather" => Feathers::$instances[$post->feather])); - } - - /** - * Function: update_post - * Updates a post when the form is submitted. - */ - public function update_post() { - $post = new Post($_POST['id'], array("drafts" => true)); - - if ($post->no_results) - Flash::warning(__("Post not found."), "/admin/?action=manage_posts"); - - if (!$post->editable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this post.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - Feathers::$instances[$post->feather]->update($post); - - if (!isset($_POST['ajax'])) - Flash::notice(_f("Post updated. View Post →", - array($post->url())), - "/admin/?action=manage_posts"); - else - exit((string) $_POST['id']); - } - - /** - * Function: delete_post - * Post deletion (confirm page). - */ - public function delete_post() { - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to delete a post.")); - - $post = new Post($_GET['id'], array("drafts" => true)); - - if (!$post->deletable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete this post.")); - - $this->display("delete_post", array("post" => $post)); - } - - /** - * Function: destroy_post - * Destroys a post (the real deal). - */ - public function destroy_post() { - if (empty($_POST['id'])) - error(__("No ID Specified"), __("An ID is required to delete a post.")); - - if ($_POST['destroy'] == "bollocks") - redirect("/admin/?action=manage_posts"); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $post = new Post($_POST['id'], array("drafts" => true)); - if (!$post->deletable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete this post.")); - - Post::delete($_POST['id']); - - Flash::notice(__("Post deleted."), "/admin/?action=manage_posts"); - } - - /** - * Function: manage_posts - * Post managing. - */ - public function manage_posts() { - if (!Post::any_editable() and !Post::any_deletable()) - show_403(__("Access Denied"), __("You do not have sufficient privileges to manage any posts.")); - - fallback($_GET['query'], ""); - - list($where, $params) = keywords($_GET['query'], "post_attributes.value LIKE :query OR url LIKE :query", "post_attributes"); - - if (!empty($_GET['month'])) - $where["created_at like"] = $_GET['month']."-%"; - - $visitor = Visitor::current(); - if (!$visitor->group->can("view_draft", "edit_draft", "edit_post", "delete_draft", "delete_post")) - $where["user_id"] = $visitor->id; - - $results = Post::find(array("placeholders" => true, - "drafts" => true, - "where" => $where, - "params" => $params)); - - $ids = array(); - foreach ($results[0] as $result) - $ids[] = $result["id"]; - - if (!empty($ids)) - $posts = new Paginator(Post::find(array("placeholders" => true, - "drafts" => true, - "where" => array("id" => $ids))), - 25); - else - $posts = new Paginator(array()); - - foreach ($posts->paginated as &$post) { - if (preg_match_all("/\{([0-9]+)\}/", $post->status, $matches)) { - $groups = array(); - $groupClasses = array(); - - foreach ($matches[1] as $id) { - $group = new Group($id); - $groups[] = "Group: ".$group->name; - $groupClasses[] = "group-".$id; - } - - $post->status_name = join(", ", $groups); - $post->status_class = join(" ", $groupClasses); - } else { - $post->status_name = camelize($post->status, true); - $post->status_class = $post->status; - } - } - - $this->display("manage_posts", array("posts" => $posts)); - } - - /** - * Function: write_page - * Page creation. - */ - public function write_page() { - if (!Visitor::current()->group->can("add_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create pages.")); - - $this->display("write_page", array("pages" => Page::find())); - } - - /** - * Function: add_page - * Adds a page when the form is submitted. - */ - public function add_page() { - if (!Visitor::current()->group->can("add_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create pages.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - if (empty($_POST['title']) and empty($_POST['slug'])) - error(__("Error"), __("Title and slug cannot be blank.")); - - $page = Page::add($_POST['title'], - $_POST['body'], - null, - $_POST['parent_id'], - !empty($_POST['show_in_list']), - 0, - (!empty($_POST['slug']) ? $_POST['slug'] : sanitize($_POST['title']))); - - Flash::notice(__("Page created!"), $page->url()); - } - - /** - * Function: edit_page - * Page editing. - */ - public function edit_page() { - if (!Visitor::current()->group->can("edit_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this page.")); - - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to edit a page.")); - - $this->display("edit_page", - array("page" => new Page($_GET['id'], array("filter" => false)), - "pages" => Page::find(array("where" => array("id not" => $_GET['id']))))); - } - - /** - * Function: update_page - * Updates a page when the form is submitted. - */ - public function update_page() { - if (!Visitor::current()->group->can("edit_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit pages.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - if (empty($_POST['title']) and empty($_POST['slug'])) - error(__("Error"), __("Title and slug cannot be blank.")); - - $page = new Page($_POST['id']); - - if ($page->no_results) - Flash::warning(__("Page not found."), "/admin/?action=manage_pages"); - - $page->update($_POST['title'], $_POST['body'], null, $_POST['parent_id'], !empty($_POST['show_in_list']), $page->list_order, null, $_POST['slug']); - - if (!isset($_POST['ajax'])) - Flash::notice(_f("Page updated. View Page →", - array($page->url())), - "/admin/?action=manage_pages"); - } - - /** - * Function: reorder_pages - * Reorders pages. - */ - public function reorder_pages() { - foreach ($_POST['list_order'] as $id => $order) { - $page = new Page($id); - $page->update($page->title, $page->body, null, $page->parent_id, $page->show_in_list, $order, null, $page->url); - } - - Flash::notice(__("Pages reordered."), "/admin/?action=manage_pages"); - } - - /** - * Function: delete_page - * Page deletion (confirm page). - */ - public function delete_page() { - if (!Visitor::current()->group->can("delete_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete pages.")); - - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to delete a page.")); - - $this->display("delete_page", array("page" => new Page($_GET['id']))); - } - - /** - * Function: destroy_page - * Destroys a page. - */ - public function destroy_page() { - if (!Visitor::current()->group->can("delete_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete pages.")); - - if (empty($_POST['id'])) - error(__("No ID Specified"), __("An ID is required to delete a post.")); - - if ($_POST['destroy'] == "bollocks") - redirect("/admin/?action=manage_pages"); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $page = new Page($_POST['id']); - - if (!$page->no_results) - foreach ($page->children as $child) - if (isset($_POST['destroy_children'])) - Page::delete($child->id, true); - else - $child->update($child->title, $child->body, 0, $child->show_in_list, $child->list_order, $child->url); - - Page::delete($_POST['id']); - - Flash::notice(__("Page deleted."), "/admin/?action=manage_pages"); - } - - /** - * Function: manage_pages - * Page managing. - */ - public function manage_pages() { - $visitor = Visitor::current(); - if (!$visitor->group->can("edit_page") and !$visitor->group->can("delete_page")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to manage pages.")); - - fallback($_GET['query'], ""); - list($where, $params) = keywords($_GET['query'], "title LIKE :query OR body LIKE :query", "pages"); - - $this->display("manage_pages", - array("pages" => new Paginator(Page::find(array("placeholders" => true, - "where" => $where, - "params" => $params)), 25))); - } - - /** - * Function: new_user - * User creation. - */ - public function new_user() { - if (!Visitor::current()->group->can("add_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to add users.")); - - $config = Config::current(); - - $this->display("new_user", - array("default_group" => new Group($config->default_group), - "groups" => Group::find(array("where" => array("id not" => array($config->guest_group, - $config->default_group)), - "order" => "id DESC")))); - } - - /** - * Function: add_user - * Add a user when the form is submitted. - */ - public function add_user() { - if (!Visitor::current()->group->can("add_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to add users.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - if (empty($_POST['login'])) - error(__("Error"), __("Please enter a username for your account.")); - - $check = new User(array("login" => $_POST['login'])); - if (!$check->no_results) - error(__("Error"), __("That username is already in use.")); - - if (empty($_POST['password1']) or empty($_POST['password2'])) - error(__("Error"), __("Password cannot be blank.")); - elseif ($_POST['password1'] != $_POST['password2']) - error(__("Error"), __("Passwords do not match.")); - - if (empty($_POST['email'])) - error(__("Error"), __("E-mail address cannot be blank.")); - elseif (!preg_match("/^[_A-z0-9-]+((\.|\+)[_A-z0-9-]+)*@[A-z0-9-]+(\.[A-z0-9-]+)*(\.[A-z]{2,4})$/", $_POST['email'])) - error(__("Error"), __("Invalid e-mail address.")); - - if (!empty($_POST['website']) and strpos($_POST['website'], '://') === false) { - $_POST['website'] = 'http://' . $_POST['website']; - } - - User::add($_POST['login'], - $_POST['password1'], - $_POST['email'], - $_POST['full_name'], - $_POST['website'], - $_POST['group']); - - Flash::notice(__("User added."), "/admin/?action=manage_users"); - } - - /** - * Function: edit_user - * User editing. - */ - public function edit_user() { - if (!Visitor::current()->group->can("edit_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this user.")); - - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to edit a user.")); - - $this->display("edit_user", - array("user" => new User($_GET['id']), - "groups" => Group::find(array("order" => "id ASC", - "where" => array("id not" => Config::current()->guest_group))))); - } - - /** - * Function: update_user - * Updates a user when the form is submitted. - */ - public function update_user() { - if (empty($_POST['id'])) - error(__("No ID Specified"), __("An ID is required to edit a user.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $visitor = Visitor::current(); - - if (!$visitor->group->can("edit_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit users.")); - - $check_name = new User(null, array("where" => array("login" => $_POST['login'], - "id not" => $_POST['id']))); - - if (!$check_name->no_results) - Flash::notice(_f("Login “%s” is already in use.", array($_POST['login'])), - "/admin/?action=edit_user&id=".$_POST['id']); - - $user = new User($_POST['id']); - - if ($user->no_results) - Flash::warning(__("User not found."), "/admin/?action=manage_user"); - - $password = (!empty($_POST['new_password1']) and $_POST['new_password1'] == $_POST['new_password2']) ? - User::hashPassword($_POST['new_password1']) : - $user->password ; - - $website = (!empty($_POST['website']) and strpos($_POST['website'], '://') === false) ? - $_POST['website'] = 'http://' . $_POST['website'] : - $_POST['website'] ; - - $user->update($_POST['login'], $password, $_POST['email'], $_POST['full_name'], $website, $_POST['group']); - - if ($_POST['id'] == $visitor->id) - $_SESSION['password'] = $password; - - Flash::notice(__("User updated."), "/admin/?action=manage_users"); - } - - /** - * Function: delete_user - * User deletion. - */ - public function delete_user() { - if (!Visitor::current()->group->can("delete_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete users.")); - - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to delete a user.")); - - $this->display("delete_user", - array("user" => new User($_GET['id']), - "users" => User::find(array("where" => array("id not" => $_GET['id']))))); - } - - /** - * Function: destroy_user - * Destroys a user. - */ - public function destroy_user() { - if (!Visitor::current()->group->can("delete_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete users.")); - - if (empty($_POST['id'])) - error(__("No ID Specified"), __("An ID is required to delete a user.")); - - if ($_POST['destroy'] == "bollocks") - redirect("/admin/?action=manage_users"); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $sql = SQL::current(); - $user = new User($_POST['id']); - - if (isset($_POST['posts'])) { - if ($_POST['posts'] == "delete") - foreach ($user->post as $post) - Post::delete($post->id); - elseif ($_POST['posts'] == "move") - $sql->update("posts", - array("user_id" => $user->id), - array("user_id" => $_POST['move_posts'])); - } - - if (isset($_POST['pages'])) { - if ($_POST['pages'] == "delete") - foreach ($user->page as $page) - Page::delete($page->id); - elseif ($_POST['pages'] == "move") - $sql->update("pages", - array("user_id" => $user->id), - array("user_id" => $_POST['move_pages'])); - } - - User::delete($_POST['id']); - - Flash::notice(__("User deleted."), "/admin/?action=manage_users"); - } - - /** - * Function: manage_users - * User managing. - */ - public function manage_users() { - $visitor = Visitor::current(); - if (!$visitor->group->can("edit_user") and !$visitor->group->can("delete_user") and !$visitor->group->can("add_user")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to manage users.")); - - fallback($_GET['query'], ""); - list($where, $params) = keywords($_GET['query'], "login LIKE :query OR full_name LIKE :query OR email LIKE :query OR website LIKE :query", "users"); - - $this->display("manage_users", - array("users" => new Paginator(User::find(array("placeholders" => true, - "where" => $where, - "params" => $params)), - 25))); - } - - /** - * Function: new_group - * Group creation. - */ - public function new_group() { - if (!Visitor::current()->group->can("add_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create groups.")); - - $this->display("new_group", - array("permissions" => SQL::current()->select("permissions", "*", array("group_id" => 0))->fetchAll())); - } - - /** - * Function: add_group - * Adds a group when the form is submitted. - */ - public function add_group() { - if (!Visitor::current()->group->can("add_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to create groups.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - Group::add($_POST['name'], array_keys($_POST['permissions'])); - - Flash::notice(__("Group added."), "/admin/?action=manage_groups"); - } - - /** - * Function: edit_group - * Group editing. - */ - public function edit_group() { - if (!Visitor::current()->group->can("edit_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit groups.")); - - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to edit a group.")); - - $this->display("edit_group", - array("group" => new Group($_GET['id']), - "permissions" => SQL::current()->select("permissions", "*", array("group_id" => 0))->fetchAll())); - } - - /** - * Function: update_group - * Updates a group when the form is submitted. - */ - public function update_group() { - if (!Visitor::current()->group->can("edit_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to edit groups.")); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $permissions = array_keys($_POST['permissions']); - - $check_name = new Group(null, array("where" => array("name" => $_POST['name'], - "id not" => $_POST['id']))); - - if (!$check_name->no_results) - Flash::notice(_f("Group name “%s” is already in use.", array($_POST['name'])), - "/admin/?action=edit_group&id=".$_POST['id']); - - $group = new Group($_POST['id']); - - if ($group->no_results) - Flash::warning(__("Group not found."), "/admin/?action=manage_groups"); - - $group->update($_POST['name'], $permissions); - - Flash::notice(__("Group updated."), "/admin/?action=manage_groups"); - } - - /** - * Function: delete_group - * Group deletion (confirm page). - */ - public function delete_group() { - if (!Visitor::current()->group->can("delete_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete groups.")); - - if (empty($_GET['id'])) - error(__("No ID Specified"), __("An ID is required to delete a group.")); - - $this->display("delete_group", - array("group" => new Group($_GET['id']), - "groups" => Group::find(array("where" => array("id not" => $_GET['id']), - "order" => "id ASC")))); - } - - /** - * Function: destroy_group - * Destroys a group. - */ - public function destroy_group() { - if (!Visitor::current()->group->can("delete_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to delete groups.")); - - if (!isset($_POST['id'])) - error(__("No ID Specified"), __("An ID is required to delete a group.")); - - if ($_POST['destroy'] == "bollocks") - redirect("/admin/?action=manage_groups"); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $group = new Group($_POST['id']); - foreach ($group->users as $user) - $user->update($user->login, $user->password, $user->email, $user->full_name, $user->website, $_POST['move_group']); - - $config = Config::current(); - if (!empty($_POST['default_group'])) - $config->set("default_group", $_POST['default_group']); - if (!empty($_POST['guest_group'])) - $config->set("guest_group", $_POST['guest_group']); - - Group::delete($_POST['id']); - - Flash::notice(__("Group deleted."), "/admin/?action=manage_groups"); - } - - /** - * Function: manage_groups - * Group managing. - */ - public function manage_groups() { - $visitor = Visitor::current(); - if (!$visitor->group->can("edit_group") and !$visitor->group->can("delete_group") and !$visitor->group->can("add_group")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to manage groups.")); - - if (!empty($_GET['search'])) { - $user = new User(array("login" => $_GET['search'])); - if (!$user->no_results) - $groups = new Paginator(array($user->group), 10); - else - $groups = new Paginator(array(), 10); - } else - $groups = new Paginator(Group::find(array("placeholders" => true, "order" => "id ASC")), 10); - - $this->display("manage_groups", - array("groups" => $groups)); - } - - /** - * Function: export - * Export posts, pages, etc. - */ - public function export() { - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to export content.")); - - if (empty($_POST)) - return $this->display("export"); - - $config = Config::current(); - $trigger = Trigger::current(); - $route = Route::current(); - $exports = array(); - - if (isset($_POST['posts'])) { - list($where, $params) = keywords($_POST['filter_posts'], "post_attributes.value LIKE :query OR url LIKE :query", "post_attributes"); - - if (!empty($_GET['month'])) - $where["created_at like"] = $_GET['month']."-%"; - - $visitor = Visitor::current(); - if (!$visitor->group->can("view_draft", "edit_draft", "edit_post", "delete_draft", "delete_post")) - $where["user_id"] = $visitor->id; - - $results = Post::find(array("placeholders" => true, - "drafts" => true, - "where" => $where, - "params" => $params)); - - $ids = array(); - foreach ($results[0] as $result) - $ids[] = $result["id"]; - - if (!empty($ids)) - $posts = Post::find(array("drafts" => true, - "where" => array("id" => $ids), - "order" => "id ASC"), - array("filter" => false)); - else - $posts = new Paginator(array()); - - $latest_timestamp = 0; - foreach ($posts as $post) - if (strtotime($post->created_at) > $latest_timestamp) - $latest_timestamp = strtotime($post->created_at); - - $id = substr(strstr($config->url, "//"), 2); - $id = str_replace("#", "/", $id); - $id = preg_replace("/(".preg_quote(parse_url($config->url, PHP_URL_HOST)).")/", "\\1,".date("Y", $latest_timestamp).":", $id, 1); - - $posts_atom = ''."\r"; - $posts_atom.= ''."\r"; - $posts_atom.= ' '.fix($config->name).' Posts'."\r"; - $posts_atom.= ' '.fix($config->description).''."\r"; - $posts_atom.= ' tag:'.parse_url($config->url, PHP_URL_HOST).','.date("Y", $latest_timestamp).':Chyrp'."\r"; - $posts_atom.= ' '.date("c", $latest_timestamp).''."\r"; - $posts_atom.= ' '."\r"; - $posts_atom.= ' Chyrp'."\r"; - - foreach ($posts as $post) { - $title = fix($post->title(), false); - fallback($title, ucfirst($post->feather)." Post #".$post->id); - - $updated = ($post->updated) ? $post->updated_at : $post->created_at ; - - $tagged = substr(strstr(url("id/".$post->id), "//"), 2); - $tagged = str_replace("#", "/", $tagged); - $tagged = preg_replace("/(".preg_quote(parse_url($post->url(), PHP_URL_HOST)).")/", "\\1,".when("Y-m-d", $updated).":", $tagged, 1); - - $url = $post->url(); - $posts_atom.= ' '."\r"; - $posts_atom.= ' '.$title.''."\r"; - $posts_atom.= ' tag:'.$tagged.''."\r"; - $posts_atom.= ' '.when("c", $updated).''."\r"; - $posts_atom.= ' '.when("c", $post->created_at).''."\r"; - $posts_atom.= ' '."\r"; - $posts_atom.= ' '."\r"; - $posts_atom.= ' '.fix(oneof($post->user->full_name, $post->user->login)).''."\r"; - - if (!empty($post->user->website)) - $posts_atom.= ' '.fix($post->user->website).''."\r"; - - $posts_atom.= ' '.fix($post->user->login).''."\r"; - $posts_atom.= ' '."\r"; - $posts_atom.= ' '."\r"; - - foreach ($post->attributes as $key => $val) - $posts_atom.= ' <'.$key.'>'.fix($val).''."\r"; - - $posts_atom.= ' '."\r"; - - foreach (array("feather", "clean", "url", "pinned", "status") as $attr) - $posts_atom.= ' '.fix($post->$attr).''."\r"; - - $trigger->filter($posts_atom, "posts_export", $post); - - $posts_atom.= ' '."\r"; - - } - $posts_atom.= ''."\r"; - - $exports["posts.atom"] = $posts_atom; - } - - if (isset($_POST['pages'])) { - list($where, $params) = keywords($_POST['filter_pages'], "title LIKE :query OR body LIKE :query", "pages"); - - $pages = Page::find(array("where" => $where, "params" => $params, "order" => "id ASC"), - array("filter" => false)); - - $latest_timestamp = 0; - foreach ($pages as $page) - if (strtotime($page->created_at) > $latest_timestamp) - $latest_timestamp = strtotime($page->created_at); - - $pages_atom = ''."\r"; - $pages_atom.= ''."\r"; - $pages_atom.= ' '.fix($config->name).' Pages'."\r"; - $pages_atom.= ' '.fix($config->description).''."\r"; - $pages_atom.= ' tag:'.parse_url($config->url, PHP_URL_HOST).','.date("Y", $latest_timestamp).':Chyrp'."\r"; - $pages_atom.= ' '.date("c", $latest_timestamp).''."\r"; - $pages_atom.= ' '."\r"; - $pages_atom.= ' Chyrp'."\r"; - - foreach ($pages as $page) { - $updated = ($page->updated) ? $page->updated_at : $page->created_at ; - - $tagged = substr(strstr($page->url(), "//"), 2); - $tagged = str_replace("#", "/", $tagged); - $tagged = preg_replace("/(".preg_quote(parse_url($page->url(), PHP_URL_HOST)).")/", "\\1,".when("Y-m-d", $updated).":", $tagged, 1); - - $url = $page->url(); - $pages_atom.= ' '."\r"; - $pages_atom.= ' '.fix($page->title).''."\r"; - $pages_atom.= ' tag:'.$tagged.''."\r"; - $pages_atom.= ' '.when("c", $updated).''."\r"; - $pages_atom.= ' '.when("c", $page->created_at).''."\r"; - $pages_atom.= ' '."\r"; - $pages_atom.= ' '."\r"; - $pages_atom.= ' '.fix(oneof($page->user->full_name, $page->user->login)).''."\r"; - - if (!empty($page->user->website)) - $pages_atom.= ' '.fix($page->user->website).''."\r"; - - $pages_atom.= ' '.fix($page->user->login).''."\r"; - $pages_atom.= ' '."\r"; - $pages_atom.= ' '.fix($page->body).''."\r"; - - foreach (array("show_in_list", "list_order", "clean", "url") as $attr) - $pages_atom.= ' '.fix($page->$attr).''."\r"; - - - $trigger->filter($pages_atom, "pages_export", $page); - - $pages_atom.= ' '."\r"; - } - $pages_atom.= ''."\r"; - - $exports["pages.atom"] = $pages_atom; - } - - if (isset($_POST['groups'])) { - list($where, $params) = keywords($_POST['filter_groups'], "name LIKE :query", "groups"); - - $groups = Group::find(array("where" => $where, "params" => $params, "order" => "id ASC")); - - $groups_yaml = array("groups" => array(), - "permissions" => array()); - - foreach (SQL::current()->select("permissions", "*", array("group_id" => 0))->fetchAll() as $permission) - $groups_yaml["permissions"][$permission["id"]] = $permission["name"]; - - foreach ($groups as $index => $group) - $groups_yaml["groups"][$group->name] = $group->permissions; - - $exports["groups.yaml"] = YAML::dump($groups_yaml); - } - - if (isset($_POST['users'])) { - list($where, $params) = keywords($_POST['filter_users'], "login LIKE :query OR full_name LIKE :query OR email LIKE :query OR website LIKE :query", "users"); - - $users = User::find(array("where" => $where, "params" => $params, "order" => "id ASC")); - - $users_yaml = array(); - foreach ($users as $user) { - $users_yaml[$user->login] = array(); - - foreach ($user as $name => $attr) - if (!in_array($name, array("no_results", "group_id", "group", "id", "login", "belongs_to", "has_many", "has_one", "queryString"))) - $users_yaml[$user->login][$name] = $attr; - elseif ($name == "group_id") - $users_yaml[$user->login]["group"] = $user->group->name; - } - - $exports["users.yaml"] = YAML::dump($users_yaml); - } - - $trigger->filter($exports, "export"); - - require INCLUDES_DIR."/lib/zip.php"; - - $zip = new ZipFile(); - foreach ($exports as $filename => $content) - $zip->addFile($content, $filename); - - $zip_contents = $zip->file(); - - $filename = sanitize(camelize($config->name), false, true)."_Export_".date("Y-m-d"); - header("Content-type: application/octet-stream"); - header("Content-Disposition: attachment; filename=\"".$filename.".zip\""); - header("Content-length: ".strlen($zip_contents)."\n\n"); - - echo $zip_contents; - } - - /** - * Function: import - * Importing content from other systems. - */ - public function import() { - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to import content.")); - - $this->display("import"); - } - - /** - * Function: import_chyrp - * Chyrp importing. - */ - public function import_chyrp() { - if (empty($_POST)) - redirect("/admin/?action=import"); - - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to import content.")); - - if (isset($_FILES['posts_file']) and $_FILES['posts_file']['error'] == 0) - if (!$posts = simplexml_load_file($_FILES['posts_file']['tmp_name']) or $posts->generator != "Chyrp") - Flash::warning(__("Chyrp Posts export file is invalid."), "/admin/?action=import"); - - if (isset($_FILES['pages_file']) and $_FILES['pages_file']['error'] == 0) - if (!$pages = simplexml_load_file($_FILES['pages_file']['tmp_name']) or $pages->generator != "Chyrp") - Flash::warning(__("Chyrp Pages export file is invalid."), "/admin/?action=import"); - - if (ini_get("memory_limit") < 20) - ini_set("memory_limit", "20M"); - - $trigger = Trigger::current(); - $visitor = Visitor::current(); - $sql = SQL::current(); - - function media_url_scan(&$value) { - $config = Config::current(); - - $regexp_url = preg_quote($_POST['media_url'], "/"); - if (preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/", $value, $media)) - foreach ($media[0] as $matched_url) { - $filename = upload_from_url($matched_url); - $value = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $value); - } - } - - if (isset($_FILES['groups_file']) and $_FILES['groups_file']['error'] == 0) { - $import = YAML::load($_FILES['groups_file']['tmp_name']); - - foreach ($import["groups"] as $name => $permissions) - if (!$sql->count("groups", array("name" => $name))) - $trigger->call("import_chyrp_group", Group::add($name, (array) $permissions)); - - foreach ($import["permissions"] as $id => $name) - if (!$sql->count("permissions", array("id" => $id))) - $sql->insert("permissions", array("id" => $id, "name" => $name)); - } - - if (isset($_FILES['users_file']) and $_FILES['users_file']['error'] == 0) { - $users = YAML::load($_FILES['users_file']['tmp_name']); - - foreach ($users as $login => $user) { - $group_id = $sql->select("groups", "id", array("name" => $user["group"]), "id DESC")->fetchColumn(); - - $group = ($group_id) ? $group_id : $config->default_group ; - - if (!$sql->count("users", array("login" => $login))) - $user = User::add($login, - $user["password"], - $user["email"], - $user["full_name"], - $user["website"], - $group, - $user["joined_at"]); - - $trigger->call("import_chyrp_user", $user); - } - } - - if (isset($_FILES['posts_file']) and $_FILES['posts_file']['error'] == 0) - foreach ($posts->entry as $entry) { - $chyrp = $entry->children("http://chyrp.net/export/1.0/"); - - $login = $entry->author->children("http://chyrp.net/export/1.0/")->login; - $user_id = $sql->select("users", "id", array("login" => $login), "id DESC")->fetchColumn(); - - $data = xml2arr($entry->content); - $data["imported_from"] = "chyrp"; - - if (!empty($_POST['media_url'])) - array_walk_recursive($data, "media_url_scan"); - - $post = Post::add($data, - $chyrp->clean, - Post::check_url($chyrp->url), - $chyrp->feather, - ($user_id ? $user_id : $visitor->id), - (bool) (int) $chyrp->pinned, - $chyrp->status, - datetime($entry->published), - ($entry->updated == $entry->published) ? - null : - datetime($entry->updated), - "", - false); - - $trigger->call("import_chyrp_post", $entry, $post); - } - - if (isset($_FILES['pages_file']) and $_FILES['pages_file']['error'] == 0) - foreach ($pages->entry as $entry) { - $chyrp = $entry->children("http://chyrp.net/export/1.0/"); - $attr = $entry->attributes("http://chyrp.net/export/1.0/"); - - $login = $entry->author->children("http://chyrp.net/export/1.0/")->login; - $user_id = $sql->select("users", "id", array("login" => $login), "id DESC")->fetchColumn(); - - $page = Page::add($entry->title, - $entry->content, - ($user_id ? $user_id : $visitor->id), - $attr->parent_id, - (bool) (int) $chyrp->show_in_list, - $chyrp->list_order, - $chyrp->clean, - Page::check_url($chyrp->url), - datetime($entry->published), - ($entry->updated == $entry->published) ? null : datetime($entry->updated)); - - $trigger->call("import_chyrp_page", $entry, $page); - } - - Flash::notice(__("Chyrp content successfully imported!"), "/admin/?action=import"); - } - - /** - * Function: import_wordpress - * WordPress importing. - */ - public function import_wordpress() { - if (empty($_POST)) - redirect("/admin/?action=import"); - - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to import content.")); - - $config = Config::current(); - - if (!in_array("text", $config->enabled_feathers)) - error(__("Missing Feather"), __("Importing from WordPress requires the Text feather to be installed and enabled.")); - - if (ini_get("memory_limit") < 20) - ini_set("memory_limit", "20M"); - - $trigger = Trigger::current(); - - $stupid_xml = file_get_contents($_FILES['xml_file']['tmp_name']); - $sane_xml = preg_replace(array("//", "/<\/wp:comment_content>/"), - array(""), - $stupid_xml); - - $sane_xml = str_replace(array("]]>"), - array(""), - $sane_xml); - - if (!substr_count($sane_xml, "xmlns:excerpt")) - $sane_xml = preg_replace("/xmlns:content=\"([^\"]+)\"(\s+)/m", - "xmlns:content=\"\\1\"\\2xmlns:excerpt=\"http://wordpress.org/excerpt/1.0/\"\\2", - $sane_xml); - - $fix_amps_count = 1; - while ($fix_amps_count) - $sane_xml = preg_replace("/(.+)&(?!amp;)(.+)<\/wp:meta_value>/m", - "\\1&\\2", - $sane_xml, -1, $fix_amps_count); - - # Remove null (x00) characters - $sane_xml = str_replace("", "", $sane_xml); - - $xml = simplexml_load_string($sane_xml, "SimpleXMLElement", LIBXML_NOCDATA); - - if (!$xml or !substr_count($xml->channel->generator, "wordpress.org")) - Flash::warning(__("File does not seem to be a valid WordPress export file, or could not be parsed. Please check your PHP error log."), - "/admin/?action=import"); - - foreach ($xml->channel->item as $item) { - $wordpress = $item->children("http://wordpress.org/export/1.0/"); - $content = $item->children("http://purl.org/rss/1.0/modules/content/"); - if ($wordpress->status == "attachment" or $item->title == "zz_placeholder") - continue; - - $regexp_url = preg_quote($_POST['media_url'], "/"); - if (!empty($_POST['media_url']) and - preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/", - $content->encoded, - $media)) - foreach ($media[0] as $matched_url) { - $filename = upload_from_url($matched_url); - $content->encoded = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $content->encoded); - } - - $clean = (isset($wordpress->post_name)) ? $wordpress->post_name : sanitize($item->title) ; - - $pinned = (isset($wordpress->is_sticky)) ? $wordpress->is_sticky : 0 ; - - if (empty($wordpress->post_type) or $wordpress->post_type == "post") { - $status_translate = array("publish" => "public", - "draft" => "draft", - "private" => "private", - "static" => "public", - "object" => "public", - "inherit" => "public", - "future" => "draft", - "pending" => "draft"); - - $data = array("title" => trim($item->title), - "body" => trim($content->encoded), - "imported_from" => "wordpress"); - - $post = Post::add($data, - $clean, - Post::check_url($clean), - "text", - null, - $pinned, - $status_translate[(string) $wordpress->status], - (string) ($wordpress->post_date == "0000-00-00 00:00:00" ? datetime() : $wordpress->post_date), - null, - "", - false); - - $trigger->call("import_wordpress_post", $item, $post); - } elseif ($wordpress->post_type == "page") { - $page = Page::add(trim($item->title), - trim($content->encoded), - null, - 0, - true, - 0, - $clean, - Page::check_url($clean), - (string) ($wordpress->post_date == "0000-00-00 00:00:00" ? datetime() : $wordpress->post_date)); - - $trigger->call("import_wordpress_page", $item, $page); - } - } - - Flash::notice(__("WordPress content successfully imported!"), "/admin/?action=import"); - } - - /** - * Function: import_tumblr - * Tumblr importing. - */ - public function import_tumblr() { - if (empty($_POST)) - redirect("/admin/?action=import"); - - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to import content.")); - - $config = Config::current(); - if (!in_array("text", $config->enabled_feathers) or - !in_array("video", $config->enabled_feathers) or - !in_array("audio", $config->enabled_feathers) or - !in_array("chat", $config->enabled_feathers) or - !in_array("photo", $config->enabled_feathers) or - !in_array("quote", $config->enabled_feathers) or - !in_array("link", $config->enabled_feathers)) - error(__("Missing Feather"), __("Importing from Tumblr requires the Text, Video, Audio, Chat, Photo, Quote, and Link feathers to be installed and enabled.")); - - if (ini_get("memory_limit") < 20) - ini_set("memory_limit", "20M"); - - if (!parse_url($_POST['tumblr_url'], PHP_URL_SCHEME)) - $_POST['tumblr_url'] = "http://".$_POST['tumblr_url']; - - set_time_limit(3600); - $url = rtrim($_POST['tumblr_url'], "/")."/api/read?num=50"; - $api = preg_replace("/<(\/?)([a-z]+)\-([a-z]+)/", "<\\1\\2_\\3", get_remote($url)); - $api = preg_replace("/ ([a-z]+)\-([a-z]+)=/", " \\1_\\2=", $api); - $xml = simplexml_load_string($api); - - if (!isset($xml->tumblelog)) - Flash::warning(_f("Content could not be retrieved from the given URL. ". get_remote($url)), - "/admin/?action=import"); - - $already_in = $posts = array(); - foreach ($xml->posts->post as $post) { - $posts[] = $post; - $already_in[] = $post->attributes()->id; - } - - while ($xml->posts->attributes()->total > count($posts)) { - set_time_limit(3600); - $api = preg_replace("/<(\/?)([a-z]+)\-([a-z]+)/", "<\\1\\2_\\3", get_remote($url."&start=".count($posts))); - $api = preg_replace("/ ([a-z]+)\-([a-z]+)=/", " \\1_\\2=", $api); - $xml = simplexml_load_string($api, "SimpleXMLElement", LIBXML_NOCDATA); - foreach ($xml->posts->post as $post) - if (!in_array($post->attributes()->id, $already_in)) { - $posts[] = $post; - $already_in[] = $post->attributes()->id; - } - } - - function reverse($a, $b) { - if (empty($a) or empty($b)) return 0; - return (strtotime($a->attributes()->date) < strtotime($b->attributes()->date)) ? -1 : 1 ; - } - - set_time_limit(3600); - usort($posts, "reverse"); - - foreach ($posts as $key => $post) { - set_time_limit(3600); - if ($post->attributes()->type == "audio") - break; # Can't import Audio posts since Tumblr has the files locked in to Amazon. - - $translate_types = array("regular" => "text", "conversation" => "chat"); - - $clean = ""; - switch($post->attributes()->type) { - case "regular": - $title = fallback($post->regular_title); - $values = array("title" => $title, - "body" => $post->regular_body); - $clean = sanitize($title); - break; - case "video": - $values = array("embed" => $post->video_player, - "caption" => fallback($post->video_caption)); - break; - case "conversation": - $title = fallback($post->conversation_title); - - $lines = array(); - foreach ($post->conversation_line as $line) - $lines[] = $line->attributes()->label." ".$line; - - $values = array("title" => $title, - "dialogue" => implode("\n", $lines)); - $clean = sanitize($title); - break; - case "photo": - $values = array("filename" => upload_from_url($post->photo_url[0]), - "caption" => fallback($post->photo_caption)); - break; - case "quote": - $values = array("quote" => $post->quote_text, - "source" => preg_replace("/^— /", "", - fallback($post->quote_source))); - break; - case "link": - $name = fallback($post->link_text); - $values = array("name" => $name, - "source" => $post->link_url, - "description" => fallback($post->link_description)); - $clean = sanitize($name); - break; - } - - $values["imported_from"] = "tumblr"; - - $new_post = Post::add($values, - $clean, - Post::check_url($clean), - fallback($translate_types[(string) $post->attributes()->type], (string) $post->attributes()->type), - null, - null, - "public", - datetime((int) $post->attributes()->unix_timestamp), - null, - "", - false); - - Trigger::current()->call("import_tumble", $post, $new_post); - } - - Flash::notice(__("Tumblr content successfully imported!"), "/admin/?action=import"); - } - - /** - * Function: import_textpattern - * TextPattern importing. - */ - public function import_textpattern() { - if (empty($_POST)) - redirect("/admin/?action=import"); - - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to import content.")); - - $config = Config::current(); - $trigger = Trigger::current(); - - $dbcon = $dbsel = false; - if ($link = @mysql_connect($_POST['host'], $_POST['username'], $_POST['password'])) { - $dbcon = true; - $dbsel = @mysql_select_db($_POST['database'], $link); - } - - if (!$dbcon or !$dbsel) - Flash::warning(__("Could not connect to the specified TextPattern database."), - "/admin/?action=import"); - - mysql_query("SET NAMES 'utf8'"); - - $get_posts = mysql_query("SELECT * FROM {$_POST['prefix']}textpattern ORDER BY ID ASC", $link) or error(__("Database Error"), mysql_error()); - $posts = array(); - while ($post = mysql_fetch_array($get_posts)) - $posts[$post["ID"]] = $post; - - foreach ($posts as $post) { - $regexp_url = preg_quote($_POST['media_url'], "/"); - if (!empty($_POST['media_url']) and - preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/", - $post["Body"], - $media)) - foreach ($media[0] as $matched_url) { - $filename = upload_from_url($matched_url); - $post["Body"] = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $post["Body"]); - } - - $status_translate = array(1 => "draft", - 2 => "private", - 3 => "draft", - 4 => "public", - 5 => "public"); - - $clean = fallback($post["url_title"], sanitize($post["Title"])); - - $new_post = Post::add(array("title" => $post["Title"], - "body" => $post["Body"], - "imported_from" => "textpattern"), - $clean, - Post::check_url($clean), - "text", - null, - ($post["Status"] == "5"), - $status_translate[$post["Status"]], - $post["Posted"], - null, - "", - false); - - $trigger->call("import_textpattern_post", $post, $new_post); - } - - mysql_close($link); - - Flash::notice(__("TextPattern content successfully imported!"), "/admin/?action=import"); - } - - /** - * Function: import_movabletype - * MovableType importing. - */ - public function import_movabletype() { - if (empty($_POST)) - redirect("/admin/?action=import"); - - if (!Visitor::current()->group->can("add_post")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to import content.")); - - $config = Config::current(); - $trigger = Trigger::current(); - - $dbcon = $dbsel = false; - if ($link = @mysql_connect($_POST['host'], $_POST['username'], $_POST['password'])) { - $dbcon = true; - $dbsel = @mysql_select_db($_POST['database'], $link); - } - - if (!$dbcon or !$dbsel) - Flash::warning(__("Could not connect to the specified MovableType database."), - "/admin/?action=import"); - - mysql_query("SET NAMES 'utf8'"); - - $get_authors = mysql_query("SELECT * FROM mt_author ORDER BY author_id ASC", $link) or error(__("Database Error"), mysql_error()); - $users = array(); - while ($author = mysql_fetch_array($get_authors)) { - # Try to figure out if this author is the same as the person doing the import. - if ($author["author_name"] == Visitor::current()->login or - $author["author_nickname"] == Visitor::current()->login or - $author["author_nickname"] == Visitor::current()->full_name or - $author["author_url"] == Visitor::current()->website or - $author["author_email"] == Visitor::current()->email) - $users[$author["author_id"]] = Visitor::current(); - else - $users[$author["author_id"]] = User::add($author["author_name"], - $author["author_password"], - $author["author_email"], - ($author["author_nickname"] != $author["author_name"] ? - $author["author_nickname"] : - ""), - $author["author_url"], - ($author["author_can_create_blog"] == "1" ? - Visitor::current()->group : - null), - $author["author_created_on"], - false); - } - - $get_posts = mysql_query("SELECT * FROM mt_entry ORDER BY entry_id ASC", $link) or error(__("Database Error"), mysql_error()); - $posts = array(); - while ($post = mysql_fetch_array($get_posts)) - $posts[$post["entry_id"]] = $post; - - foreach ($posts as $post) { - $body = $post["entry_text"]; - - if (!empty($post["entry_text_more"])) - $body.= "\n\n\n\n".$post["entry_text_more"]; - - $regexp_url = preg_quote($_POST['media_url'], "/"); - if (!empty($_POST['media_url']) and - preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/", - $body, - $media)) - foreach ($media[0] as $matched_url) { - $filename = upload_from_url($matched_url); - $body = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $body); - } - - $status_translate = array(1 => "draft", - 2 => "public", - 3 => "draft", - 4 => "draft"); - - $clean = oneof($post["entry_basename"], sanitize($post["entry_title"])); - - if (empty($post["entry_class"]) or $post["entry_class"] == "entry") { - $new_post = Post::add(array("title" => $post["entry_title"], - "body" => $body, - "imported_from" => "movabletype"), - $clean, - Post::check_url($clean), - "text", - @$users[$post["entry_author_id"]], - false, - $status_translate[$post["entry_status"]], - oneof(@$post["entry_authored_on"], @$post["entry_created_on"], datetime()), - $post["entry_modified_on"], - "", - false); - $trigger->call("import_movabletype_post", $post, $new_post, $link); - } elseif (@$post["entry_class"] == "page") { - $new_page = Page::add($post["entry_title"], $body, null, 0, true, 0, $clean, Page::check_url($clean)); - $trigger->call("import_movabletype_page", $post, $new_page, $link); - } - } - - mysql_close($link); - - Flash::notice(__("MovableType content successfully imported!"), "/admin/?action=import"); - } - - /** - * Function: modules - * Module enabling/disabling. - */ - public function modules() { - if (!Visitor::current()->group->can("toggle_extensions")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable modules.")); - - $config = Config::current(); - - $this->context["enabled_modules"] = $this->context["disabled_modules"] = array(); - - if (!$open = @opendir(MODULES_DIR)) - return Flash::warning(__("Could not read modules directory.")); - - $classes = array(); - - while (($folder = readdir($open)) !== false) { - if (!file_exists(MODULES_DIR."/".$folder."/".$folder.".php") or !file_exists(MODULES_DIR."/".$folder."/info.yaml")) continue; - - if (file_exists(MODULES_DIR."/".$folder."/locale/".$config->locale.".mo")) - load_translator($folder, MODULES_DIR."/".$folder."/locale/".$config->locale.".mo"); - - if (!isset($classes[$folder])) - $classes[$folder] = array($folder); - else - array_unshift($classes[$folder], $folder); - - $info = YAML::load(MODULES_DIR."/".$folder."/info.yaml"); - - $info["conflicts_true"] = array(); - $info["depends_true"] = array(); - - if (!empty($info["conflicts"])) { - $classes[$folder][] = "conflict"; - - foreach ((array) $info["conflicts"] as $conflict) - if (file_exists(MODULES_DIR."/".$conflict."/".$conflict.".php")) - $classes[$folder][] = "conflict_".$conflict; - } - - $dependencies_needed = array(); - if (!empty($info["depends"])) { - $classes[$folder][] = "depends"; - - foreach ((array) $info["depends"] as $dependency) { - if (!module_enabled($dependency)) { - if (!in_array("missing_dependency", $classes[$folder])) - $classes[$folder][] = "missing_dependency"; - - $classes[$folder][] = "needs_".$dependency; - - $dependencies_needed[] = $dependency; - } - - $classes[$folder][] = "depends_".$dependency; - - fallback($classes[$dependency], array()); - $classes[$dependency][] = "depended_by_".$folder; - } - } - - fallback($info["name"], $folder); - fallback($info["version"], "0"); - fallback($info["url"]); - fallback($info["description"]); - fallback($info["author"], array("name" => "", "url" => "")); - fallback($info["help"]); - - $info["description"] = __($info["description"], $folder); - $info["description"] = preg_replace(array("/(.+)<\/code>/se", "/
(.+)<\/pre>/se"),
-                                                    array("''.fix('\\1').''", "'
'.fix('\\1').'
'"), - $info["description"]); - - $info["author"]["link"] = !empty($info["author"]["url"]) ? - ''.fix($info["author"]["name"]).'' : - $info["author"]["name"] ; - - $category = (module_enabled($folder)) ? "enabled_modules" : "disabled_modules" ; - $this->context[$category][$folder] = array("name" => $info["name"], - "version" => $info["version"], - "url" => $info["url"], - "description" => $info["description"], - "author" => $info["author"], - "help" => $info["help"], - "classes" => $classes[$folder], - "dependencies_needed" => $dependencies_needed); - } - - foreach ($this->context["enabled_modules"] as $module => &$attrs) - $attrs["classes"] = $classes[$module]; - - foreach ($this->context["disabled_modules"] as $module => &$attrs) - $attrs["classes"] = $classes[$module]; - - $this->display("modules"); - } - - /** - * Function: feathers - * Feather enabling/disabling. - */ - public function feathers() { - if (!Visitor::current()->group->can("toggle_extensions")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable feathers.")); - - $config = Config::current(); - - $this->context["enabled_feathers"] = $this->context["disabled_feathers"] = array(); - - if (!$open = @opendir(FEATHERS_DIR)) - return Flash::warning(__("Could not read feathers directory.")); - - while (($folder = readdir($open)) !== false) { - if (!file_exists(FEATHERS_DIR."/".$folder."/".$folder.".php") or !file_exists(FEATHERS_DIR."/".$folder."/info.yaml")) continue; - - if (file_exists(FEATHERS_DIR."/".$folder."/locale/".$config->locale.".mo")) - load_translator($folder, FEATHERS_DIR."/".$folder."/locale/".$config->locale.".mo"); - - $info = YAML::load(FEATHERS_DIR."/".$folder."/info.yaml"); - - fallback($info["name"], $folder); - fallback($info["version"], "0"); - fallback($info["url"]); - fallback($info["description"]); - fallback($info["author"], array("name" => "", "url" => "")); - fallback($info["help"]); - - $info["description"] = __($info["description"], $folder); - $info["description"] = preg_replace("/(.+)<\/code>/se", "''.fix('\\1').''", $info["description"]); - $info["description"] = preg_replace("/
(.+)<\/pre>/se", "'
'.fix('\\1').'
'", $info["description"]); - - $info["author"]["link"] = !empty($info["author"]["url"]) ? - ''.fix($info["author"]["name"]).'' : - $info["author"]["name"] ; - - $category = (feather_enabled($folder)) ? "enabled_feathers" : "disabled_feathers" ; - $this->context[$category][$folder] = array("name" => $info["name"], - "version" => $info["version"], - "url" => $info["url"], - "description" => $info["description"], - "author" => $info["author"], - "help" => $info["help"]); - } - - $this->display("feathers"); - } - - /** - * Function: themes - * Theme switching/previewing. - */ - public function themes() { - $config = Config::current(); - - $this->context["preview"] = !empty($_SESSION['theme']) ? $_SESSION['theme'] : "" ; - - $this->context["themes"] = array(); - - if (!$open = @opendir(THEMES_DIR)) - return Flash::warning(__("Could not read themes directory.")); - - while (($folder = readdir($open)) !== false) { - if (!file_exists(THEMES_DIR."/".$folder."/info.yaml")) - continue; - - if (file_exists(THEMES_DIR."/".$folder."/locale/".$config->locale.".mo")) - load_translator($folder, THEMES_DIR."/".$folder."/locale/".$config->locale.".mo"); - - $info = YAML::load(THEMES_DIR."/".$folder."/info.yaml"); - - fallback($info["name"], $folder); - fallback($info["version"], "0"); - fallback($info["url"]); - fallback($info["description"]); - fallback($info["author"], array("name" => "", "url" => "")); - - $info["author"]["link"] = !empty($info["author"]["url"]) ? - ''.$info["author"]["name"].'' : - $info["author"]["name"] ; - $info["description"] = preg_replace("/(.+)<\/code>/se", - "''.fix('\\1').''", - $info["description"]); - - $info["description"] = preg_replace("/
(.+)<\/pre>/se",
-                                                    "'
'.fix('\\1').'
'", - $info["description"]); - - $this->context["themes"][] = array("name" => $folder, - "screenshot" => (file_exists(THEMES_DIR."/".$folder."/screenshot.png") ? - $config->chyrp_url."/themes/".$folder."/screenshot.png" : - ""), - "info" => $info); - } - - if (!$open = @opendir(ADMIN_THEMES_DIR)) - return Flash::warning(__("Could not read themes directory.")); - - while (($folder = readdir($open)) !== false) { - if (!file_exists(ADMIN_THEMES_DIR."/".$folder."/info.yaml")) - continue; - - if (file_exists(ADMIN_THEMES_DIR."/".$folder."/locale/".$config->locale.".mo")) - load_translator($folder, ADMIN_THEMES_DIR."/".$folder."/locale/".$config->locale.".mo"); - - $info = YAML::load(ADMIN_THEMES_DIR."/".$folder."/info.yaml"); - - fallback($info["name"], $folder); - fallback($info["version"], "0"); - fallback($info["url"]); - fallback($info["description"]); - fallback($info["author"], array("name" => "", "url" => "")); - - $info["author"]["link"] = !empty($info["author"]["url"]) ? - ''.$info["author"]["name"].'' : - $info["author"]["name"] ; - $info["description"] = preg_replace("/(.+)<\/code>/se", - "''.fix('\\1').''", - $info["description"]); - - $info["description"] = preg_replace("/
(.+)<\/pre>/se",
-                                                    "'
'.fix('\\1').'
'", - $info["description"]); - - $this->context["admin_themes"][] = array("name" => $folder, - "screenshot" => (file_exists(ADMIN_THEMES_DIR."/".$folder."/screenshot.png") ? - $config->chyrp_url."/admin/themes/".$folder."/screenshot.png" : - ""), - "info" => $info); - } - - closedir($open); - - $this->display("themes"); - } - - /** - * Function: enable - * Enables a module or feather. - */ - public function enable() { - $config = Config::current(); - $visitor = Visitor::current(); - - $type = (isset($_GET['module'])) ? "module" : "feather" ; - - if (!$visitor->group->can("toggle_extensions")) - if ($type == "module") - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable modules.")); - else - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable feathers.")); - - if ($type == "module" and module_enabled($_GET[$type])) - Flash::warning(__("Module already enabled."), "/admin/?action=modules"); - - if ($type == "feather" and feather_enabled($_GET[$type])) - Flash::warning(__("Feather already enabled."), "/admin/?action=feathers"); - - $enabled_array = ($type == "module") ? "enabled_modules" : "enabled_feathers" ; - $folder = ($type == "module") ? MODULES_DIR : FEATHERS_DIR ; - - require $folder."/".$_GET[$type]."/".$_GET[$type].".php"; - - $class_name = camelize($_GET[$type]); - - if ($type == "module" and !is_subclass_of($class_name, "Modules")) - Flash::warning(__("Item is not a module."), "/admin/?action=modules"); - - if ($type == "feather" and !is_subclass_of($class_name, "Feathers")) - Flash::warning(__("Item is not a feather."), "/admin/?action=feathers"); - - if (method_exists($class_name, "__install")) - call_user_func(array($class_name, "__install")); - - $new = $config->$enabled_array; - array_push($new, $_GET[$type]); - $config->set($enabled_array, $new); - - if (file_exists($folder."/".$_GET[$type]."/locale/".$config->locale.".mo")) - load_translator($_GET[$type], $folder."/".$_GET[$type]."/locale/".$config->locale.".mo"); - - $info = YAML::load($folder."/".$_GET[$type]."/info.yaml"); - fallback($info["uploader"], false); - fallback($info["notifications"], array()); - - foreach ($info["notifications"] as &$notification) - $notification = __($notification, $_GET[$type]); - - if ($info["uploader"]) - if (!file_exists(MAIN_DIR.$config->uploads_path)) - $info["notifications"][] = _f("Please create the %s directory at your Chyrp install's root and CHMOD it to 777.", array($config->uploads_path)); - elseif (!is_writable(MAIN_DIR.$config->uploads_path)) - $info["notifications"][] = _f("Please CHMOD %s to 777.", array($config->uploads_path)); - - foreach ($info["notifications"] as $message) - Flash::message($message); - - if ($type == "module") - Flash::notice(_f("“%s” module enabled.", - array($info["name"])), - "/admin/?action=".pluralize($type)); - elseif ($type == "feather") - Flash::notice(_f("“%s” feather enabled.", - array($info["name"])), - "/admin/?action=".pluralize($type)); - } - - /** - * Function: disable - * Disables a module or feather. - */ - public function disable() { - $config = Config::current(); - $visitor = Visitor::current(); - - $type = (isset($_GET['module'])) ? "module" : "feather" ; - - if (!$visitor->group->can("toggle_extensions")) - if ($type == "module") - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable modules.")); - else - show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable feathers.")); - - if ($type == "module" and !module_enabled($_GET[$type])) - Flash::warning(__("Module already disabled."), "/admin/?action=modules"); - - if ($type == "feather" and !feather_enabled($_GET[$type])) - Flash::warning(__("Feather already disabled."), "/admin/?action=feathers"); - - $enabled_array = ($type == "module") ? "enabled_modules" : "enabled_feathers" ; - $folder = ($type == "module") ? MODULES_DIR : FEATHERS_DIR ; - - $class_name = camelize($_GET[$type]); - if (method_exists($class_name, "__uninstall")) - call_user_func(array($class_name, "__uninstall"), false); - - $config->set(($type == "module" ? "enabled_modules" : "enabled_feathers"), - array_diff($config->$enabled_array, array($_GET[$type]))); - - $info = YAML::load($folder."/".$_GET[$type]."/info.yaml"); - if ($type == "module") - Flash::notice(_f("“%s” module disabled.", - array($info["name"])), - "/admin/?action=".pluralize($type)); - elseif ($type == "feather") - Flash::notice(_f("“%s” feather disabled.", - array($info["name"])), - "/admin/?action=".pluralize($type)); - } - - /** - * Function: change_theme - * Changes the theme. - */ - public function change_theme() { - if (!Visitor::current()->group->can("change_settings")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings.")); - if (empty($_GET['theme'])) - error(__("No Theme Specified"), __("You did not specify a theme to switch to.")); - - $config = Config::current(); - - $config->set("theme", $_GET['theme']); - - if (file_exists(THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo")) - load_translator($_GET['theme'], THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo"); - - $info = YAML::load(THEMES_DIR."/".$_GET['theme']."/info.yaml"); - fallback($info["notifications"], array()); - - foreach ($info["notifications"] as &$notification) - $notification = __($notification, $_GET['theme']); - - foreach ($info["notifications"] as $message) - Flash::message($message); - - # Clear the caches made by the previous theme. - foreach ((array) glob(INCLUDES_DIR."/caches/*.cache") as $cache) - @unlink($cache); - - Flash::notice(_f("Theme changed to “%s”.", array($info["name"])), "/admin/?action=themes"); - } - - /** - * Function: theme - * Changes the admin theme. - */ - public function change_admin_theme() { - if (empty($_GET['theme'])) - error(__("No Theme Specified"), __("You did not specify a theme to switch to.")); - - $config = Config::current(); - - $_SESSION['admin_theme'] = $_GET['theme']; - - if (file_exists(ADMIN_THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo")) - load_translator($_GET['theme'], ADMIN_THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo"); - - $info = YAML::load(ADMIN_THEMES_DIR."/".$_GET['theme']."/info.yaml"); - fallback($info["notifications"], array()); - - foreach ($info["notifications"] as &$notification) - $notification = __($notification, $_GET['theme']); - - foreach ($info["notifications"] as $message) - Flash::message($message); - - # Clear the caches made by the previous theme. - foreach (glob(INCLUDES_DIR."/caches/*.cache") as $cache) - @unlink($cache); - - Flash::notice(_f("Admin theme changed to “%s”.", array($info["name"])), "/admin/?action=themes"); - } - - /** - * Function: preview_theme - * Previews the theme. - */ - public function preview_theme() { - if (!Visitor::current()->group->can("change_settings")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to preview themes.")); - if (empty($_GET['theme'])) - error(__("No Theme Specified"), __("You did not specify a theme to preview.")); - - $info = YAML::load(THEMES_DIR."/".$_GET['theme']."/info.yaml"); - - # Clear the caches made by the previous theme. - foreach (glob(INCLUDES_DIR."/caches/*.cache") as $cache) - @unlink($cache); - - if (!empty($_SESSION['theme'])) { - unset($_SESSION['theme']); - Flash::notice(_f("Stopped previewing “%s”.", array($info["name"])), "/admin/?action=themes"); - } else { - $_SESSION['theme'] = $_GET['theme']; - Flash::notice(_f("Previewing theme “%s”. Press the theme's “Preview” button again to stop previewing.", array($info["name"])), "/"); - } - } - - /** - * Function: general_settings - * General Settings page. - */ - public function general_settings() { - if (!Visitor::current()->group->can("change_settings")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings.")); - - $locales = array(); - - if ($open = opendir(INCLUDES_DIR."/locale/")) { - while (($folder = readdir($open)) !== false) { - $split = explode(".", $folder); - if (end($split) == "mo") - $locales[] = array("code" => $split[0], "name" => lang_code($split[0])); - } - closedir($open); - } - - if (empty($_POST)) - return $this->display("general_settings", - array("locales" => $locales, - "timezones" => timezones())); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $config = Config::current(); - $set = array($config->set("name", $_POST['name']), - $config->set("description", $_POST['description']), - $config->set("chyrp_url", rtrim($_POST['chyrp_url'], "/")), - $config->set("url", rtrim(oneof($_POST['url'], $_POST['chyrp_url']), "/")), - $config->set("email", $_POST['email']), - $config->set("timezone", $_POST['timezone']), - $config->set("locale", $_POST['locale'])); - - if (!in_array(false, $set)) - Flash::notice(__("Settings updated."), "/admin/?action=general_settings"); - } - - /** - * Function: user_settings - * User Settings page. - */ - public function user_settings() { - if (!Visitor::current()->group->can("change_settings")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings.")); - - if (empty($_POST)) - return $this->display("user_settings", array("groups" => Group::find(array("order" => "id DESC")))); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $config = Config::current(); - $set = array($config->set("can_register", !empty($_POST['can_register'])), - $config->set("default_group", $_POST['default_group']), - $config->set("guest_group", $_POST['guest_group'])); - - if (!in_array(false, $set)) - Flash::notice(__("Settings updated."), "/admin/?action=user_settings"); - } - - /** - * Function: content_settings - * Content Settings page. - */ - public function content_settings() { - if (!Visitor::current()->group->can("change_settings")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings.")); - - if (empty($_POST)) - return $this->display("content_settings"); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $config = Config::current(); - $set = array($config->set("posts_per_page", $_POST['posts_per_page']), - $config->set("feed_items", $_POST['feed_items']), - $config->set("feed_url", $_POST['feed_url']), - $config->set("uploads_path", $_POST['uploads_path']), - $config->set("enable_trackbacking", !empty($_POST['enable_trackbacking'])), - $config->set("send_pingbacks", !empty($_POST['send_pingbacks'])), - $config->set("enable_xmlrpc", !empty($_POST['enable_xmlrpc'])), - $config->set("enable_ajax", !empty($_POST['enable_ajax']))); - - if (!in_array(false, $set)) - Flash::notice(__("Settings updated."), "/admin/?action=content_settings"); - } - - /** - * Function: route_settings - * Route Settings page. - */ - public function route_settings() { - if (!Visitor::current()->group->can("change_settings")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings.")); - - if (empty($_POST)) - return $this->display("route_settings"); - - if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey) - show_403(__("Access Denied"), __("Invalid security key.")); - - $config = Config::current(); - $set = array($config->set("clean_urls", !empty($_POST['clean_urls'])), - $config->set("post_url", $_POST['post_url'])); - - if (!in_array(false, $set)) - Flash::notice(__("Settings updated."), "/admin/?action=route_settings"); - } - - /** - * Function: help - * Sets the $title and $body for various help IDs. - */ - public function help() { - list($title, $body) = Trigger::current()->call("help_".$_GET['id']); - - switch($_GET['id']) { - case "filtering_results": - $title = __("Filtering Results"); - $body = "

".__("Use this to search for specific items. You can either enter plain text to match the item with, or use keywords:")."

"; - $body.= "

".__("Keywords")."

"; - $body.= "".__("Usage").": attr:val\n".__("Use this syntax to quickly match specific results. Keywords will modify the query to match items where attr is equal to val (case insensitive)."); - break; - case "slugs": - $title = __("Post Slugs"); - $body = __("Post slugs are strings to use for the URL of a post. They are directly respondible for the (url) attribute in a post's clean URL, or the /?action=view&url=foo in a post's dirty URL. A post slug should not contain any special characters other than hyphens."); - break; - case "trackbacks": - $title = __("Trackbacks"); - $body = __("Trackbacks are special urls to posts from other blogs that your post is related to or references. The other blog will be notified of your post, and in some cases a comment will automatically be added to the post in question linking back to your post. It's basically a way to network between blogs via posts."); - break; - case "alternate_urls": - $title = __("Alternate URL"); - $body = "

".__("An alternate URL will allow you to keep Chyrp in its own directory, while having your site URLs point to someplace else. For example, you could have Chyrp in a /chyrp directory, and have your site at /. There are two requirements for this to work.")."

\n\n"; - $body.= "
    \n\t
  1. ".__("Create an index.php file in your destination directory with the following in it:")."\n\n"; - $body.= "
    <?php
    -    require \"path/to/chyrp/index.php\";
    -?>
    "; - $body.= "
  2. \n\t
  3. ".__("Move the .htaccess file from the original Chyrp directory, and change the RewriteBase line to reflect the new website location.")."
  4. \n
"; - } - - require "help.php"; - } - - /** - * Function: subnav_context - * Generates the context variables for the subnav. - */ - public function subnav_context($action) { - $trigger = Trigger::current(); - $visitor = Visitor::current(); - - $this->context["subnav"] = array(); - $subnav =& $this->context["subnav"]; - - $subnav["write"] = array(); - $pages = array("manage" => array()); - - foreach (Config::current()->enabled_feathers as $index => $feather) { - $info = YAML::load(FEATHERS_DIR."/".$feather."/info.yaml"); - $subnav["write"]["write_post&feather=".$feather] = array("title" => __($info["name"], $feather), - "show" => $visitor->group->can("add_draft", "add_post"), - "attributes" => ' id="list_feathers['.$feather.']"', - "selected" => (isset($_GET['feather']) and $_GET['feather'] == $feather) or - (!isset($_GET['feather']) and $action == "write_post" and !$index)); - } - - # Write navs - $subnav["write"]["write_page"] = array("title" => __("Page"), - "show" => $visitor->group->can("add_page")); - $trigger->filter($subnav["write"], array("admin_write_nav", "write_nav")); - $pages["write"] = array_merge(array("write_post"), array_keys($subnav["write"]));; - - # Manage navs - $subnav["manage"] = array("manage_posts" => array("title" => __("Posts"), - "show" => (Post::any_editable() or Post::any_deletable()), - "selected" => array("edit_post", "delete_post")), - "manage_pages" => array("title" => __("Pages"), - "show" => ($visitor->group->can("edit_page", "delete_page")), - "selected" => array("edit_page", "delete_page")), - "manage_users" => array("title" => __("Users"), - "show" => ($visitor->group->can("add_user", - "edit_user", - "delete_user")), - "selected" => array("edit_user", "delete_user", "new_user")), - "manage_groups" => array("title" => __("Groups"), - "show" => ($visitor->group->can("add_group", - "edit_group", - "delete_group")), - "selected" => array("edit_group", "delete_group", "new_group"))); - $trigger->filter($subnav["manage"], "manage_nav"); - - $subnav["manage"]["import"] = array("title" => __("Import"), - "show" => ($visitor->group->can("add_post"))); - $subnav["manage"]["export"] = array("title" => __("Export"), - "show" => ($visitor->group->can("add_post"))); - - $pages["manage"][] = "new_user"; - $pages["manage"][] = "new_group"; - foreach (array_keys($subnav["manage"]) as $manage) - $pages["manage"] = array_merge($pages["manage"], array($manage, - preg_replace("/manage_(.+)/e", - "'edit_'.depluralize('\\1')", - $manage), - preg_replace("/manage_(.+)/e", - "'delete_'.depluralize('\\1')", - $manage))); - - # Settings navs - $subnav["settings"] = array("general_settings" => array("title" => __("General"), - "show" => $visitor->group->can("change_settings")), - "content_settings" => array("title" => __("Content"), - "show" => $visitor->group->can("change_settings")), - "user_settings" => array("title" => __("Users"), - "show" => $visitor->group->can("change_settings")), - "route_settings" => array("title" => __("Routes"), - "show" => $visitor->group->can("change_settings"))); - $trigger->filter($subnav["settings"], "settings_nav"); - $pages["settings"] = array_keys($subnav["settings"]); - - # Extend navs - $subnav["extend"] = array("modules" => array("title" => __("Modules"), - "show" => $visitor->group->can("toggle_extensions")), - "feathers" => array("title" => __("Feathers"), - "show" => $visitor->group->can("toggle_extensions")), - "themes" => array("title" => __("Themes"), - "show" => $visitor->group->can("toggle_extensions"))); - $trigger->filter($subnav["extend"], "extend_nav"); - $pages["extend"] = array_keys($subnav["extend"]); - - foreach (array_keys($subnav) as $main_nav) - foreach ($trigger->filter($pages[$main_nav], $main_nav."_nav_pages") as $extend) - $subnav[$extend] =& $subnav[$main_nav]; - - foreach ($subnav as $main_nav => &$sub_nav) - foreach ($sub_nav as &$nav) - $nav["show"] = (!isset($nav["show"]) or $nav["show"]); - - $trigger->filter($subnav, "admin_subnav"); - } - - /** - * Function: display - * Renders the page. - * - * Parameters: - * $action - The template file to display, in (theme dir)/pages. - * $context - Context for the template. - * $title - The title for the page. Defaults to a camlelization of the action, e.g. foo_bar -> Foo Bar. - */ - public function display($action, $context = array(), $title = "") { - $this->displayed = true; - - fallback($title, camelize($action, true)); - - $this->context = array_merge($context, $this->context); - - $trigger = Trigger::current(); - - $trigger->filter($this->context, array("admin_context", "admin_context_".str_replace("/", "_", $action))); - - # Are there any extension-added pages? - foreach (array("write" => array(), - "manage" => array("import", "export"), - "settings" => array(), - "extend" => array("modules", "feathers", "themes")) as $main_nav => $val) { - $$main_nav = $val; - $trigger->filter($$main_nav, $main_nav."_pages"); - } - - $visitor = Visitor::current(); - $route = Route::current(); - - $this->context["theme"] = Theme::current(); - $this->context["flash"] = Flash::current(); - $this->context["trigger"] = $trigger; - $this->context["title"] = $title; - $this->context["site"] = Config::current(); - $this->context["visitor"] = $visitor; - $this->context["logged_in"] = logged_in(); - $this->context["route"] = $route; - $this->context["hide_admin"] = isset($_SESSION["hide_admin"]); - $this->context["now"] = time(); - $this->context["version"] = CHYRP_VERSION; - $this->context["debug"] = DEBUG; - $this->context["feathers"] = Feathers::$instances; - $this->context["modules"] = Modules::$instances; - $this->context["admin_theme"] = $this->admin_theme; - $this->context["theme_url"] = Config::current()->chyrp_url."/admin/themes/".$this->admin_theme; - $this->context["POST"] = $_POST; - $this->context["GET"] = $_GET; - - $this->context["navigation"] = array(); - - $show = array("write" => array($visitor->group->can("add_draft", "add_post", "add_page")), - "manage" => array($visitor->group->can("view_own_draft", - "view_draft", - "edit_own_draft", - "edit_own_post", - "edit_post", - "delete_own_draft", - "delete_own_post", - "delete_post", - "add_page", - "edit_page", - "delete_page", - "add_user", - "edit_user", - "delete_user", - "add_group", - "edit_group", - "delete_group")), - "settings" => array($visitor->group->can("change_settings")), - "extend" => array($visitor->group->can("toggle_extensions"))); - - foreach ($show as $name => &$arr) - $trigger->filter($arr, $name."_nav_show"); - - $this->context["navigation"]["write"] = array("title" => __("Write"), - "show" => in_array(true, $show["write"]), - "selected" => (in_array($action, $write) or - match("/^write_/", $action))); - - $this->context["navigation"]["manage"] = array("title" => __("Manage"), - "show" => in_array(true, $show["manage"]), - "selected" => (in_array($action, $manage) or - match(array("/^manage_/", - "/^edit_/", - "/^delete_/", - "/^new_/"), $action))); - - $this->context["navigation"]["settings"] = array("title" => __("Settings"), - "show" => in_array(true, $show["settings"]), - "selected" => (in_array($action, $settings) or - match("/_settings$/", $action))); - - $this->context["navigation"]["extend"] = array("title" => __("Extend"), - "show" => in_array(true, $show["extend"]), - "selected" => (in_array($action, $extend))); - - $this->subnav_context($route->action); - - $trigger->filter($this->context["selected"], "nav_selected"); - - $this->context["sql_debug"] = SQL::current()->debug; - - $file = MAIN_DIR."/admin/themes/%s/pages/".$action.".twig"; - $template = file_exists(sprintf($file, $this->admin_theme)) ? - sprintf($file, $this->admin_theme) : - sprintf($file, "default"); - - $config = Config::current(); - if (!file_exists($template)) { - foreach (array(MODULES_DIR => $config->enabled_modules, - FEATHERS_DIR => $config->enabled_feathers) as $path => $try) - foreach ($try as $extension) - if (file_exists($path."/".$extension."/pages/admin/".$action.".twig")) - $template = $path."/".$extension."/pages/admin/".$action.".twig"; - - if (!file_exists($template)) - error(__("Template Missing"), _f("Couldn't load template: %s", array($template))); - } - - # Try the theme first - try { - $this->theme->getTemplate($template)->display($this->context); - } catch (Exception $t) { - # Fallback to the default - try { - $this->default->getTemplate($template)->display($this->context); - } catch (Exception $e) { - $prettify = preg_replace("/([^:]+): (.+)/", "\\1: \\2", $e->getMessage()); - $trace = debug_backtrace(); - $twig = array("file" => $e->filename, "line" => $e->lineno); - array_unshift($trace, $twig); - error(__("Error"), $prettify, $trace); - } - } - } - - /** - * Function: current - * Returns a singleton reference to the current class. - */ - public static function & current() { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } diff --git a/News/includes/controller/Main.php b/News/includes/controller/Main.php deleted file mode 100755 index fc3a55a..0000000 --- a/News/includes/controller/Main.php +++ /dev/null @@ -1,767 +0,0 @@ - dirty URL translations. - public $urls = array('|/id/([0-9]+)/|' => '/?action=view&id=$1', - '|/page/(([^/]+)/)+|' => '/?action=page&url=$2', - '|/search/|' => '/?action=search', - '|/search/([^/]+)/|' => '/?action=search&query=$1', - '|/archive/([0-9]{4})/([0-9]{2})/|' - => '/?action=archive&year=$1&month=$2', - '|/archive/([0-9]{4})/([0-9]{2})/([0-9]{2})/|' - => '/?action=archive&year=$1&month=$2&day=$3', - '|/([^/]+)/feed/([^/]+)/|' => '/?action=$1&feed&title=$2', - '|/([^/]+)/feed/|' => '/?action=$1&feed'); - - # Boolean: $displayed - # Has anything been displayed? - public $displayed = false; - - # Array: $context - # Context for displaying pages. - public $context = array(); - - # Boolean: $feed - # Is the visitor requesting a feed? - public $feed = false; - - /** - * Function: __construct - * Loads the Twig parser into , and sets up the theme l10n domain. - */ - private function __construct() { - $this->feed = (isset($_GET['feed']) or (isset($_GET['action']) and $_GET['action'] == "feed")); - $this->post_limit = Config::current()->posts_per_page; - - $cache = (is_writable(INCLUDES_DIR."/caches") and - !DEBUG and - !PREVIEWING and - !defined('CACHE_TWIG') or CACHE_TWIG); - - if (defined('THEME_DIR')) - $this->twig = new Twig_Loader(THEME_DIR, - $cache ? - INCLUDES_DIR."/caches" : - null) ; - } - - /** - * Function: parse - * Determines the action. - */ - public function parse($route) { - $config = Config::current(); - - if (empty($route->arg[0]) and !isset($config->routes["/"])) # If they're just at /, don't bother with all this. - return $route->action = "index"; - - # Protect non-responder functions. - if (in_array($route->arg[0], array("__construct", "parse", "post_from_url", "display", "current"))) - show_404(); - - # Feed - if (preg_match("/\/feed\/?$/", $route->request)) { - $this->feed = true; - $this->post_limit = $config->feed_items; - - if ($route->arg[0] == "feed") # Don't set $route->action to "feed" (bottom of this function). - return $route->action = "index"; - } - - # Feed with a title parameter - if (preg_match("/\/feed\/([^\/]+)\/?$/", $route->request, $title)) { - $this->feed = true; - $this->post_limit = $config->feed_items; - $_GET['title'] = $title[1]; - - if ($route->arg[0] == "feed") # Don't set $route->action to "feed" (bottom of this function). - return $route->action = "index"; - } - - # Paginator - if (preg_match_all("/\/((([^_\/]+)_)?page)\/([0-9]+)/", $route->request, $page_matches)) { - foreach ($page_matches[1] as $key => $page_var) - $_GET[$page_var] = (int) $page_matches[4][$key]; - - if ($route->arg[0] == $page_matches[1][0]) # Don't fool ourselves into thinking we're viewing a page. - return $route->action = (isset($config->routes["/"])) ? $config->routes["/"] : "index" ; - } - - # Viewing a post by its ID - if ($route->arg[0] == "id") { - $_GET['id'] = $route->arg[1]; - return $route->action = "id"; - } - - # Archive - if ($route->arg[0] == "archive") { - # Make sure they're numeric; there might be a /page/ in there. - if (isset($route->arg[1]) and is_numeric($route->arg[1])) - $_GET['year'] = $route->arg[1]; - if (isset($route->arg[2]) and is_numeric($route->arg[2])) - $_GET['month'] = $route->arg[2]; - if (isset($route->arg[3]) and is_numeric($route->arg[3])) - $_GET['day'] = $route->arg[3]; - - return $route->action = "archive"; - } - - # Searching - if ($route->arg[0] == "search") { - if (isset($route->arg[1])) - $_GET['query'] = $route->arg[1]; - - return $route->action = "search"; - } - - # Custom pages added by Modules, Feathers, Themes, etc. - foreach ($config->routes as $path => $action) { - if (is_numeric($action)) - $action = $route->arg[0]; - - preg_match_all("/\(([^\)]+)\)/", $path, $matches); - - if ($path != "/") - $path = trim($path, "/"); - - $escape = preg_quote($path, "/"); - $to_regexp = preg_replace("/\\\\\(([^\)]+)\\\\\)/", "([^\/]+)", $escape); - - if ($path == "/") - $to_regexp = "\$"; - - if (preg_match("/^\/{$to_regexp}/", $route->request, $url_matches)) { - array_shift($url_matches); - - if (isset($matches[1])) - foreach ($matches[1] as $index => $parameter) - $_GET[$parameter] = urldecode($url_matches[$index]); - - $params = explode(";", $action); - $action = $params[0]; - - array_shift($params); - foreach ($params as $param) { - $split = explode("=", $param); - $_GET[$split[0]] = oneof(@$split[1], ""); - } - - $route->action = $action; - } - } - - # Are we viewing a post? - $this->post_from_url($route, $route->request); - - # Try viewing a page. - $route->try["page"] = array($route->arg); - } - - /** - * Function: post_from_url - * Check to see if we're viewing a post, and if it is, handle it. - * - * This can also be used for grabbing a Post from a given URL. - * - * Parameters: - * $route - The route to respond to. - * $url - If this argument is passed, it will attempt to grab a post from a given URL. - * If a post is found by that URL, it will be returned. - * $return_post - Return a Post? - */ - public function post_from_url($route, $request, $return_post = false) { - $config = Config::current(); - - $post_url = $config->post_url; - - foreach (explode("/", $post_url) as $path) - foreach (preg_split("/\(([^\)]+)\)/", $path) as $leftover) { - $request = preg_replace("/".preg_quote($leftover)."/", "", $request, 1); - $post_url = preg_replace("/".preg_quote($leftover)."/", "", $post_url, 1); - } - - $args = array_map("urldecode", explode("/", trim($request, "/"))); - - $post_url = $this->key_regexp(rtrim($post_url, "/")); - $post_url_attrs = array(); - preg_match_all("/\(([^\/]+)\)/", $config->post_url, $parameters); - if (preg_match("/".$post_url."/", rtrim($request, "/"), $matches)) { - array_shift($matches); - - foreach ($parameters[0] as $index => $parameter) - if ($parameter[0] == "(") { - if ($parameter == "(id)") { - $post_url_attrs = array("id" => $args[$index]); - break; - } else - $post_url_attrs[rtrim(ltrim($parameter, "("), ")")] = $args[$index]; - } - - if ($return_post) - return Post::from_url($post_url_attrs); - else - $route->try["view"] = array($post_url_attrs, $args); - } - } - - /** - * Function: key_regexp - * Converts the values in $config->post_url to regular expressions. - * - * Parameters: - * $key - Input URL with the keys from . - * - * Returns: - * $key values replaced with their regular expressions from $code>. - */ - private function key_regexp($key) { - Trigger::current()->filter(Post::$url_attrs, "url_code"); - return str_replace(array_keys(Post::$url_attrs), array_values(Post::$url_attrs), str_replace("/", "\\/", $key)); - } - - /** - * Function: index - * Grabs the posts for the main page. - */ - public function index() { - $this->display("pages/index", - array("posts" => new Paginator(Post::find(array("placeholders" => true)), - $this->post_limit))); - } - - /** - * Function: archive - * Grabs the posts for the Archive page when viewing a year or a month. - */ - public function archive() { - fallback($_GET['year']); - fallback($_GET['month']); - fallback($_GET['day']); - - if (isset($_GET['year']) and isset($_GET['month']) and isset($_GET['day'])) - $posts = new Paginator(Post::find(array("placeholders" => true, - "where" => array("YEAR(created_at)" => $_GET['year'], - "MONTH(created_at)" => $_GET['month'], - "DAY(created_at)" => $_GET['day']))), - $this->post_limit); - elseif (isset($_GET['year']) and isset($_GET['month'])) - $posts = new Paginator(Post::find(array("placeholders" => true, - "where" => array("YEAR(created_at)" => $_GET['year'], - "MONTH(created_at)" => $_GET['month']))), - $this->post_limit); - - $sql = SQL::current(); - - if (empty($_GET['year']) or empty($_GET['month'])) { - if (!empty($_GET['year'])) - $timestamps = $sql->select("posts", - array("DISTINCT YEAR(created_at) AS year", - "MONTH(created_at) AS month", - "created_at AS created_at", - "id"), - array("YEAR(created_at)" => $_GET['year']), - array("created_at DESC", "id DESC"), - array(), - null, - null, - array("YEAR(created_at)", "MONTH(created_at)", "created_at", "id")); - else - $timestamps = $sql->select("posts", - array("DISTINCT YEAR(created_at) AS year", - "MONTH(created_at) AS month", - "created_at AS created_at", - "id"), - null, - array("created_at DESC", "id DESC"), - array(), - null, - null, - array("YEAR(created_at)", "MONTH(created_at)", "created_at", "id")); - - $archives = array(); - $archive_hierarchy = array(); - while ($time = $timestamps->fetchObject()) { - $year = mktime(0, 0, 0, 1, 0, $time->year); - $month = mktime(0, 0, 0, $time->month + 1, 0, $time->year); - - $posts = Post::find(array("where" => array("YEAR(created_at)" => when("Y", $time->created_at), - "MONTH(created_at)" => when("m", $time->created_at)))); - - $archives[$month] = array("posts" => $posts, - "year" => $time->year, - "month" => strftime("%B", $month), - "timestamp" => $month, - "url" => url("archive/".when("Y/m/", $time->created_at))); - - $archive_hierarchy[$year][$month] = $posts; - } - - $this->display("pages/archive", - array("archives" => $archives, - "archive_hierarchy" => $archive_hierarchy), - __("Archive")); - } else { - if (!is_numeric($_GET['year']) or !is_numeric($_GET['month'])) - error(__("Error"), __("Please enter a valid year and month.")); - - $timestamp = mktime(0, 0, 0, $_GET['month'], oneof(@$_GET['day'], 1), $_GET['year']); - $depth = isset($_GET['day']) ? "day" : (isset($_GET['month']) ? "month" : (isset($_GET['year']) ? "year" : "")); - - $this->display("pages/archive", - array("posts" => $posts, - "archive" => array("year" => $_GET['year'], - "month" => strftime("%B", $timestamp), - "day" => strftime("%d", $timestamp), - "timestamp" => $timestamp, - "depth" => $depth)), - _f("Archive of %s", array(strftime("%B %Y", $timestamp)))); - } - } - - /** - * Function: search - * Grabs the posts for a search query. - */ - public function search() { - fallback($_GET['query'], ""); - $config = Config::current(); - - if ($config->clean_urls and - substr_count($_SERVER['REQUEST_URI'], "?") and - !substr_count($_SERVER['REQUEST_URI'], "%2F")) # Searches with / and clean URLs = server 404 - redirect("search/".urlencode($_GET['query'])."/"); - - if (empty($_GET['query'])) - return Flash::warning(__("Please enter a search term.")); - - list($where, $params) = keywords($_GET['query'], "post_attributes.value LIKE :query OR url LIKE :query", "posts"); - - $results = Post::find(array("placeholders" => true, - "where" => $where, - "params" => $params)); - - $ids = array(); - foreach ($results[0] as $result) - $ids[] = $result["id"]; - - if (!empty($ids)) - $posts = new Paginator(Post::find(array("placeholders" => true, - "where" => array("id" => $ids))), - $this->post_limit); - else - $posts = new Paginator(array()); - - $this->display(array("pages/search", "pages/index"), - array("posts" => $posts, - "search" => $_GET['query']), - fix(_f("Search results for \"%s\"", array($_GET['query'])))); - } - - /** - * Function: drafts - * Grabs the posts for viewing the Drafts lists. - */ - public function drafts() { - $visitor = Visitor::current(); - - if (!$visitor->group->can("view_own_draft", "view_draft")) - show_403(__("Access Denied"), __("You do not have sufficient privileges to view drafts.")); - - $posts = new Paginator(Post::find(array("placeholders" => true, - "where" => array("status" => "draft", - "user_id" => $visitor->id))), - $this->post_limit); - - $this->display(array("pages/drafts", "pages/index"), - array("posts" => $posts), - __("Drafts")); - } - - /** - * Function: view - * Views a post. - */ - public function view($attrs = null, $args = array()) { - if (isset($attrs)) - $post = Post::from_url($attrs, array("drafts" => true)); - else - $post = new Post(array("url" => @$_GET['url']), array("drafts" => true)); - - if ($post->no_results) - return false; - - if ((oneof(@$attrs["url"], @$attrs["clean"]) == "feed") and # do some checking to see if they're trying - (count(explode("/", trim($post_url, "/"))) > count($args) or # to view the post or the post's feed. - end($args) != "feed")) - $this->feed = false; - - if (!$post->theme_exists()) - error(__("Error"), __("The feather theme file for this post does not exist. The post cannot be displayed.")); - - if ($post->status == "draft") - Flash::message(__("This post is a draft.")); - - if ($post->groups() and !substr_count($post->status, "{".Visitor::current()->group->id."}")) - Flash::message(_f("This post is only visible by the following groups: %s.", $post->groups())); - - $this->display(array("pages/view", "pages/index"), - array("post" => $post, "posts" => array($post)), - $post->title()); - } - - /** - * Function: page - * Handles page viewing. - */ - public function page($urls = null) { - if (isset($urls)) { # Viewing with clean URLs, e.g. /parent/child/child-of-child/ - $valids = Page::find(array("where" => array("url" => $urls))); - - if (count($valids) == count($urls)) { # Make sure all page slugs are valid. - foreach ($valids as $page) - if ($page->url == end($urls)) # Loop until we reach the last one. - break; - } else - return false; # A "link in the chain" is broken - } else - $page = new Page(array("url" => $_GET['url'])); - - if ($page->no_results) - return false; # Page not found; the 404 handling is handled externally. - - $this->display(array("pages/page", "pages/".$page->url), array("page" => $page), $page->title); - } - - /** - * Function: rss - * Redirects to /feed (backwards compatibility). - */ - public function rss() { - header("HTTP/1.1 301 Moved Permanently"); - redirect(oneof(@Config::current()->feed_url, url("feed"))); - } - - /** - * Function: id - * Views a post by its static ID. - */ - public function id() { - $post = new Post($_GET['id']); - redirect($post->url()); - } - - /** - * Function: toggle_admin - * Toggles the Admin control panel (if available). - */ - public function toggle_admin() { - if (!isset($_SESSION['hide_admin'])) - $_SESSION['hide_admin'] = true; - else - unset($_SESSION['hide_admin']); - - redirect("/"); - } - - /** - * Function: register - * Process registration. If registration is disabled or if the user is already logged in, it will error. - */ - public function register() { - $config = Config::current(); - if (!$config->can_register) - error(__("Registration Disabled"), __("I'm sorry, but this site is not allowing registration.")); - - if (logged_in()) - error(__("Error"), __("You're already logged in.")); - - if (!empty($_POST)) { - $route = Route::current(); - - if (empty($_POST['login'])) - Flash::warning(__("Please enter a username for your account.")); - elseif (count(User::find(array("where" => array("login" => $_POST['login']))))) - Flash::warning(__("That username is already in use.")); - - if (empty($_POST['password1']) and empty($_POST['password2'])) - Flash::warning(__("Password cannot be blank.")); - elseif ($_POST['password1'] != $_POST['password2']) - Flash::warning(__("Passwords do not match.")); - - if (empty($_POST['email'])) - Flash::warning(__("E-mail address cannot be blank.")); - elseif (!preg_match("/^[_A-z0-9-]+((\.|\+)[_A-z0-9-]+)*@[A-z0-9-]+(\.[A-z0-9-]+)*(\.[A-z]{2,4})$/", $_POST['email'])) - Flash::warning(__("Invalid e-mail address.")); - - if (!Flash::exists("warning")) { - $user = User::add($_POST['login'], $_POST['password1'], $_POST['email']); - - Trigger::current()->call("user_registered", $user); - - $_SESSION['user_id'] = $user->id; - - Flash::notice(__("Registration successful."), "/"); - } - } - - $this->display("forms/user/register", array(), __("Register")); - } - - /** - * Function: login - * Process logging in. If the username and password are incorrect or if the user is already logged in, it will error. - */ - public function login() { - if (logged_in()) - error(__("Error"), __("You're already logged in.")); - - if (!empty($_POST)) { - fallback($_POST['login']); - fallback($_POST['password']); - - $trigger = Trigger::current(); - - if ($trigger->exists("authenticate")) - return $trigger->call("authenticate"); - - if (!User::authenticate($_POST['login'], $_POST['password'])) - if (!count(User::find(array("where" => array("login" => $_POST['login']))))) - Flash::warning(__("There is no user with that login name.")); - else - Flash::warning(__("Password incorrect.")); - - if (!Flash::exists("warning")) { - $user = new User(array("login" => $_POST['login'])); - $_SESSION['user_id'] = $user->id; - - $redirect = $_SESSION['redirect_to']; - unset($_SESSION['redirect_to']); - - Flash::notice(__("Logged in."), oneof($redirect, "/")); - } - } - - $this->display("forms/user/login", array(), __("Log In")); - } - - /** - * Function: logout - * Logs the current user out. If they are not logged in, it will error. - */ - public function logout() { - if (!logged_in()) - error(__("Error"), __("You aren't logged in.")); - - session_destroy(); - - session(); - - Flash::notice(__("Logged out."), "/"); - } - - /** - * Function: controls - * Updates the current user when the form is submitted. Shows an error if they aren't logged in. - */ - public function controls() { - if (!logged_in()) - error(__("Error"), __("You must be logged in to access this area.")); - - if (!empty($_POST)) { - $visitor = Visitor::current(); - - $password = (!empty($_POST['new_password1']) and $_POST['new_password1'] == $_POST['new_password2']) ? - User::hashPassword($_POST['new_password1']) : - $visitor->password ; - - $visitor->update($visitor->login, - $password, - $_POST['email'], - $_POST['full_name'], - $_POST['website'], - $visitor->group->id); - - Flash::notice(__("Your profile has been updated."), "/"); - } - - $this->display("forms/user/controls", array(), __("Controls")); - } - - /** - * Function: lost_password - * Handles e-mailing lost passwords to a user's email address. - */ - public function lost_password() { - if (!empty($_POST)) { - $user = new User(array("login" => $_POST['login'])); - if ($user->no_results) { - Flash::warning(__("Invalid user specified.")); - return $this->display("forms/user/lost_password", array(), __("Lost Password")); - } - - $new_password = random(16); - - $user->update($user->login, - User::hashPassword($new_password), - $user->email, - $user->full_name, - $user->website, - $user->group_id); - - $sent = email($user->email, - __("Lost Password Request"), - _f("%s,\n\nWe have received a request for a new password for your account at %s.\n\nPlease log in with the following password, and feel free to change it once you've successfully logged in:\n\t%s", - array($user->login, Config::current()->name, $new_password))); - - if ($sent) - Flash::notice(_f("An e-mail has been sent to your e-mail address that contains a new password. Once you have logged in, you can change it at User Controls.", - array(url("controls")))); - else { - # Set their password back to what it was originally. - $user->update($user->login, - $user->password, - $user->email, - $user->full_name, - $user->website, - $user->group_id); - - Flash::warning(__("E-Mail could not be sent. Password change cancelled.")); - } - } - - $this->display("forms/user/lost_password", array(), __("Lost Password")); - } - - /** - * Function: feed - * Grabs posts for the feed. - */ - public function feed($posts = null) { - fallback($posts, Post::find(array("limit" => Config::current()->feed_items))); - - header("Content-Type: application/atom+xml; charset=UTF-8"); - - if (!is_array($posts)) - $posts = $posts->paginated; - - $latest_timestamp = 0; - foreach ($posts as $post) - if (strtotime($post->created_at) > $latest_timestamp) - $latest_timestamp = strtotime($post->created_at); - - require INCLUDES_DIR."/feed.php"; - } - - /** - * Function: display - * Display the page. - * - * If "posts" is in the context and the visitor requested a feed, they will be served. - * - * Parameters: - * $file - The theme file to display. - * $context - The context for the file. - * $title - The title for the page. - */ - public function display($file, $context = array(), $title = "") { - if (is_array($file)) - for ($i = 0; $i < count($file); $i++) { - $check = ($file[$i][0] == "/" or preg_match("/[a-zA-Z]:\\\/", $file[$i])) ? - $file[$i] : - THEME_DIR."/".$file[$i] ; - - if (file_exists($check.".twig") or ($i + 1) == count($file)) - return $this->display($file[$i], $context, $title); - } - - $this->displayed = true; - - $route = Route::current(); - $trigger = Trigger::current(); - - # Serve feeds. - if ($this->feed) { - if ($trigger->exists($route->action."_feed")) - return $trigger->call($route->action."_feed", $context); - - if (isset($context["posts"])) - return $this->feed($context["posts"]); - } - - $this->context = array_merge($context, $this->context); - - $visitor = Visitor::current(); - $config = Config::current(); - $theme = Theme::current(); - - $theme->title = $title; - - $this->context["theme"] = $theme; - $this->context["flash"] = Flash::current(); - $this->context["trigger"] = $trigger; - $this->context["modules"] = Modules::$instances; - $this->context["feathers"] = Feathers::$instances; - $this->context["title"] = $title; - $this->context["site"] = $config; - $this->context["visitor"] = $visitor; - $this->context["route"] = Route::current(); - $this->context["hide_admin"] = isset($_COOKIE["hide_admin"]); - $this->context["version"] = CHYRP_VERSION; - $this->context["now"] = time(); - $this->context["debug"] = DEBUG; - $this->context["POST"] = $_POST; - $this->context["GET"] = $_GET; - $this->context["sql_queries"] =& SQL::current()->queries; - - $this->context["visitor"]->logged_in = logged_in(); - - $this->context["enabled_modules"] = array(); - foreach ($config->enabled_modules as $module) - $this->context["enabled_modules"][$module] = true; - - $context["enabled_feathers"] = array(); - foreach ($config->enabled_feathers as $feather) - $this->context["enabled_feathers"][$feather] = true; - - $this->context["sql_debug"] =& SQL::current()->debug; - - $trigger->filter($this->context, array("main_context", "main_context_".str_replace("/", "_", $file))); - - $file = ($file[0] == "/" or preg_match("/[a-zA-Z]:\\\/", $file)) ? $file : THEME_DIR."/".$file ; - if (!file_exists($file.".twig")) - error(__("Template Missing"), _f("Couldn't load template: %s", array($file.".twig"))); - - try { - return $this->twig->getTemplate($file.".twig")->display($this->context); - } catch (Exception $e) { - $prettify = preg_replace("/([^:]+): (.+)/", "\\1: \\2", $e->getMessage()); - $trace = debug_backtrace(); - $twig = array("file" => $e->filename, "line" => $e->lineno); - array_unshift($trace, $twig); - error(__("Error"), $prettify, $trace); - } - } - - /** - * Function: resort - * Queue a failpage in the event that none of the routes are successful. - */ - public function resort($file, $context, $title = null) { - $this->fallback = array($file, $context, $title); - return false; - } - - /** - * Function: current - * Returns a singleton reference to the current class. - */ - public static function & current() { - static $instance = null; - return $instance = (empty($instance)) ? new self() : $instance ; - } - } - diff --git a/News/includes/error.php b/News/includes/error.php deleted file mode 100755 index 5391939..0000000 --- a/News/includes/error.php +++ /dev/null @@ -1,154 +0,0 @@ -url."/includes/lib/gz.php?file=jquery.js" : - "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" ; - - if (!class_exists("MainController")) - require INCLUDES_DIR."/controller/Main.php"; - - if (class_exists("Route")) - Route::current(MainController::current()); -?> - - - - - Chyrp: <?php echo $title; ?> - - - - - -
-

-
- - -

-
    - -
  1. - -
- -
- - " class="big login"> - -
-
-
- - - - - diff --git a/News/includes/feed.php b/News/includes/feed.php deleted file mode 100755 index 91eb8dc..0000000 --- a/News/includes/feed.php +++ /dev/null @@ -1,57 +0,0 @@ -\r"; -?> - - <?php echo $config->name.$title; ?> -description)): ?> - description); ?> - - - - - - Chyrp -updated) ? $post->updated_at : $post->created_at ; - - $tagged = substr(strstr(url("id/".$post->id), "//"), 2); - $tagged = str_replace("#", "/", $tagged); - $tagged = preg_replace("/(".preg_quote(parse_url($post->url(), PHP_URL_HOST)).")/", - "\\1,".when("Y-m-d", $updated).":", - $tagged, - 1); - - $url = $post->url(); - $title = $post->title(); - - $trigger->filter($url, "feed_url", $post); - - if (!$post->user->no_results) - $author = oneof($post->user->full_name, $post->user->login); - else - $author = __("Guest"); -?> - - <?php echo fix(oneof($title, ucfirst($post->feather))); ?> - tag: - - created_at); ?> - - - -user->website)): ?> - user->website); ?> - - - feed_content()); ?> -call("feed_item", $post); ?> - - diff --git a/News/includes/helpers.php b/News/includes/helpers.php deleted file mode 100755 index 61e7285..0000000 --- a/News/includes/helpers.php +++ /dev/null @@ -1,1632 +0,0 @@ - &$trace) - if (!isset($trace["file"]) or !isset($trace["line"])) - unset($backtrace[$index]); - else - $trace["file"] = str_replace(MAIN_DIR."/", "", $trace["file"]); - # $trace["file"] = isset($trace["file"]) ? - # : - # (isset($trace["function"]) ? - # (isset($trace["class"]) ? - # $trace["class"].$trace["type"] : - # "").$trace["function"] : - # "[internal]"); - - # Clear all output sent before this error. - if (($buffer = ob_get_contents()) !== false) { - ob_end_clean(); - - # Since the header might already be set to gzip, start output buffering again. - if (extension_loaded("zlib") and !ini_get("zlib.output_compression") and - isset($_SERVER['HTTP_ACCEPT_ENCODING']) and - substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], "gzip") and - USE_ZLIB) { - ob_start("ob_gzhandler"); - header("Content-Encoding: gzip"); - } else - ob_start(); - } elseif (!UPGRADING) { - # If output buffering is not started, assume this - # is sent from the Session class or somewhere deep. - error_log($title.": ".$body); - - foreach ($backtrace as $index => $trace) - error_log(" ".($index + 1).": "._f("%s on line %d", array($trace["file"], $trace["line"]))); - - exit; - } - - if (TESTER) - exit("ERROR: ".$body); - - if ($title == __("Access Denied")) - $_SESSION['redirect_to'] = self_url(); - - # Display the error. - if (defined('THEME_DIR') and class_exists("Theme") and Theme::current()->file_exists("pages/error")) - MainController::current()->display("pages/error", - array("title" => $title, - "body" => $body, - "backtrace" => $backtrace)); - else - require INCLUDES_DIR."/error.php"; - - if ($buffer !== false) - ob_end_flush(); - - exit; - } - - /** - * Function: show_403 - * Shows an error message with a 403 HTTP header. - * - * Parameters: - * $title - The title for the error dialog. - * $body - The message for the error dialog. - */ - function show_403($title, $body) { - header("Status: 403"); - error($title, $body); - } - - /** - * Function: logged_in - * Returns whether or not they are logged in by returning the (which defaults to 0). - */ - function logged_in() { - return (class_exists("Visitor") and isset(Visitor::current()->id) and Visitor::current()->id != 0); - } - - /** - * Function: load_translator - * Loads a .mo file for gettext translation. - * - * Parameters: - * $domain - The name for this translation domain. - * $mofile - The .mo file to read from. - */ - function load_translator($domain, $mofile) { - global $l10n; - - if (isset($l10n[$domain])) - return; - - if (is_readable($mofile)) - $input = new CachedFileReader($mofile); - else - return; - - $l10n[$domain] = new gettext_reader($input); - } - - /** - * Function: __ - * Returns a translated string. - * - * Parameters: - * $text - The string to translate. - * $domain - The translation domain to read from. - */ - function __($text, $domain = "chyrp") { - global $l10n; - return (isset($l10n[$domain])) ? $l10n[$domain]->translate($text) : $text ; - } - - /** - * Function: _p - * Returns a plural (or not) form of a translated string. - * - * Parameters: - * $single - Singular string. - * $plural - Pluralized string. - * $number - The number to judge by. - * $domain - The translation domain to read from. - */ - function _p($single, $plural, $number, $domain = "chyrp") { - global $l10n; - return isset($l10n[$domain]) ? - $l10n[$domain]->ngettext($single, $plural, $number) : - (($number != 1) ? $plural : $single) ; - } - - /** - * Function: _f - * Returns a formatted translated string. - * - * Parameters: - * $string - String to translate and format. - * $args - One arg or an array of arguments to format with. - * $domain - The translation domain to read from. - */ - function _f($string, $args = array(), $domain = "chyrp") { - $args = (array) $args; - array_unshift($args, __($string, $domain)); - return call_user_func_array("sprintf", $args); - } - - /** - * Function: redirect - * Redirects to the given URL and exits immediately. - * - * Parameters: - * $url - The URL to redirect to. If it begins with @/@ it will be relative to the @Config.chyrp_url@. - * $use_chyrp_url - Use the @Config.chyrp_url@ instead of @Config.url@ for $urls beginning with @/@? - */ - function redirect($url, $use_chyrp_url = false) { - # Handle URIs without domain - if ($url[0] == "/") - $url = (ADMIN or $use_chyrp_url) ? - Config::current()->chyrp_url.$url : - Config::current()->url.$url ; - elseif (file_exists(INCLUDES_DIR."/config.yaml.php") and class_exists("Route") and !substr_count($url, "://")) - $url = url($url); - - header("Location: ".html_entity_decode($url)); - exit; - } - - /** - * Function: url - * Mask for Route->url(). - */ - function url($url, $controller = null) { - return Route::current()->url($url, $controller); - } - - /** - * Function: pluralize - * Returns a pluralized string. This is a port of Rails's pluralizer. - * - * Parameters: - * $string - The string to pluralize. - * $number - If passed, and this number is 1, it will not pluralize. - */ - function pluralize($string, $number = null) { - $uncountable = array("moose", "sheep", "fish", "series", "species", - "rice", "money", "information", "equipment", "piss"); - - if (in_array($string, $uncountable) or $number == 1) - return $string; - - $replacements = array("/person/i" => "people", - "/man/i" => "men", - "/child/i" => "children", - "/cow/i" => "kine", - "/goose/i" => "geese", - "/(penis)$/i" => "\\1es", # Take that, Rails! - "/(ax|test)is$/i" => "\\1es", - "/(octop|vir)us$/i" => "\\1ii", - "/(cact)us$/i" => "\\1i", - "/(alias|status)$/i" => "\\1es", - "/(bu)s$/i" => "\\1ses", - "/(buffal|tomat)o$/i" => "\\1oes", - "/([ti])um$/i" => "\\1a", - "/sis$/i" => "ses", - "/(hive)$/i" => "\\1s", - "/([^aeiouy]|qu)y$/i" => "\\1ies", - "/^(ox)$/i" => "\\1en", - "/(matr|vert|ind)(?:ix|ex)$/i" => "\\1ices", - "/(x|ch|ss|sh)$/i" => "\\1es", - "/([m|l])ouse$/i" => "\\1ice", - "/(quiz)$/i" => "\\1zes"); - - $replaced = preg_replace(array_keys($replacements), array_values($replacements), $string, 1); - - if ($replaced == $string) - return $string."s"; - else - return $replaced; - } - - /** - * Function: depluralize - * Returns a depluralized string. This is the inverse of . - * - * Parameters: - * $string - The string to depluralize. - * $number - If passed, and this number is not 1, it will not depluralize. - */ - function depluralize($string, $number = null) { - if (isset($number) and $number != 1) - return $string; - - $replacements = array("/people/i" => "person", - "/^men/i" => "man", - "/children/i" => "child", - "/kine/i" => "cow", - "/geese/i" => "goose", - "/(penis)es$/i" => "\\1", - "/(ax|test)es$/i" => "\\1is", - "/(octopi|viri|cact)i$/i" => "\\1us", - "/(alias|status)es$/i" => "\\1", - "/(bu)ses$/i" => "\\1s", - "/(buffal|tomat)oes$/i" => "\\1o", - "/([ti])a$/i" => "\\1um", - "/ses$/i" => "sis", - "/(hive)s$/i" => "\\1", - "/([^aeiouy]|qu)ies$/i" => "\\1y", - "/^(ox)en$/i" => "\\1", - "/(vert|ind)ices$/i" => "\\1ex", - "/(matr)ices$/i" => "\\1ix", - "/(x|ch|ss|sh)es$/i" => "\\1", - "/([ml])ice$/i" => "\\1ouse", - "/(quiz)zes$/i" => "\\1"); - - $replaced = preg_replace(array_keys($replacements), array_values($replacements), $string, 1); - - if ($replaced == $string and substr($string, -1) == "s") - return substr($string, 0, -1); - else - return $replaced; - } - - /** - * Function: truncate - * Truncates a string to the given length, optionally taking into account HTML tags, and/or keeping words in tact. - * - * Parameters: - * $text - String to shorten. - * $length - Length to truncate to. - * $ending - What to place at the end, e.g. "...". - * $exact - Break words? - * $html - Auto-close cut-off HTML tags? - * - * Author: - * CakePHP team, code style modified. - */ - function truncate($text, $length = 100, $ending = "...", $exact = false, $html = false) { - if (is_array($ending)) - extract($ending); - - if ($html) { - if (strlen(preg_replace("/<[^>]+>/", "", $text)) <= $length) - return $text; - - $totalLength = strlen($ending); - $openTags = array(); - $truncate = ""; - preg_match_all("/(<\/?([\w+]+)[^>]*>)?([^<>]*)/", $text, $tags, PREG_SET_ORDER); - foreach ($tags as $tag) { - if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2]) - and preg_match('/<[\w]+[^>]*>/s', $tag[0])) - array_unshift($openTags, $tag[2]); - elseif (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) { - $pos = array_search($closeTag[1], $openTags); - if ($pos !== false) - array_splice($openTags, $pos, 1); - } - - $truncate .= $tag[1]; - - $contentLength = strlen(preg_replace("/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i", " ", $tag[3])); - if ($contentLength + $totalLength > $length) { - $left = $length - $totalLength; - $entitiesLength = 0; - if (preg_match_all("/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i", $tag[3], $entities, PREG_OFFSET_CAPTURE)) - foreach ($entities[0] as $entity) - if ($entity[1] + 1 - $entitiesLength <= $left) { - $left--; - $entitiesLength += strlen($entity[0]); - } else - break; - - $truncate .= substr($tag[3], 0 , $left + $entitiesLength); - - break; - } else { - $truncate .= $tag[3]; - $totalLength += $contentLength; - } - - if ($totalLength >= $length) - break; - } - } else { - if (strlen($text) <= $length) - return $text; - else - $truncate = substr($text, 0, $length - strlen($ending)); - } - - if (!$exact) { - $spacepos = strrpos($truncate, " "); - - if (isset($spacepos)) { - if ($html) { - $bits = substr($truncate, $spacepos); - preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER); - if (!empty($droppedTags)) - foreach ($droppedTags as $closingTag) - if (!in_array($closingTag[1], $openTags)) - array_unshift($openTags, $closingTag[1]); - } - - $truncate = substr($truncate, 0, $spacepos); - } - } - - $truncate .= $ending; - - if ($html) - foreach ($openTags as $tag) - $truncate .= ''; - - return $truncate; - } - - /** - * Function: when - * Returns date formatting for a string that isn't a regular time() value - * - * Parameters: - * $formatting - The formatting for date(). - * $when - Time to base on. If it is not numeric it will be run through strtotime. - * $strftime - Use @strftime@ instead of @date@? - */ - function when($formatting, $when, $strftime = false) { - $time = (is_numeric($when)) ? $when : strtotime($when) ; - - if ($strftime) - return strftime($formatting, $time); - else - return date($formatting, $time); - } - - /** - * Function: datetime - * Returns a standard datetime string based on either the passed timestamp or their time offset, usually for MySQL inserts. - * - * Parameters: - * $when - An optional timestamp. - */ - function datetime($when = null) { - fallback($when, time()); - - $time = (is_numeric($when)) ? $when : strtotime($when) ; - - return date("Y-m-d H:i:s", $time); - } - - /** - * Function: fix - * Returns a HTML-sanitized version of a string. - * - * Parameters: - * $string - String to fix. - * $quotes - Encode quotes? - */ - function fix($string, $quotes = false) { - $quotes = ($quotes) ? ENT_QUOTES : ENT_NOQUOTES ; - return htmlspecialchars($string, $quotes, "utf-8"); - } - - /** - * Function: unfix - * Returns the reverse of fix(). - * - * Parameters: - * $string - String to unfix. - */ - function unfix($string) { - return htmlspecialchars_decode($string, ENT_QUOTES, "utf-8"); - } - - /** - * Function: lang_code - * Returns the passed language code (e.g. en_US) to the human-readable text (e.g. English (US)) - * - * Parameters: - * $code - The language code to convert - * - * Author: - * TextPattern devs, modified to fit with Chyrp. - */ - function lang_code($code) { - $langs = array("ar_DZ" => "جزائري عربي", - "ca_ES" => "Català", - "cs_CZ" => "Čeština", - "da_DK" => "Dansk", - "de_DE" => "Deutsch", - "el_GR" => "Ελληνικά", - "en_GB" => "English (GB)", - "en_US" => "English (US)", - "es_ES" => "Español", - "et_EE" => "Eesti", - "fi_FI" => "Suomi", - "fr_FR" => "Français", - "gl_GZ" => "Galego (Galiza)", - "he_IL" => "עברית", - "hu_HU" => "Magyar", - "id_ID" => "Bahasa Indonesia", - "is_IS" => "Íslenska", - "it_IT" => "Italiano", - "ja_JP" => "日本語", - "lv_LV" => "Latviešu", - "nl_NL" => "Nederlands", - "no_NO" => "Norsk", - "pl_PL" => "Polski", - "pt_PT" => "Português", - "ro_RO" => "Română", - "ru_RU" => "Русский", - "sk_SK" => "Slovenčina", - "sv_SE" => "Svenska", - "th_TH" => "ไทย", - "uk_UA" => "Українська", - "vi_VN" => "Tiếng Việt", - "zh_CN" => "中文(简体)", - "zh_TW" => "中文(繁體)", - "bg_BG" => "Български"); - return (isset($langs[$code])) ? str_replace(array_keys($langs), array_values($langs), $code) : $code ; - } - - /** - * Function: sanitize - * Returns a sanitized string, typically for URLs. - * - * Parameters: - * $string - The string to sanitize. - * $force_lowercase - Force the string to lowercase? - * $anal - If set to *true*, will remove all non-alphanumeric characters. - * $trunc - Number of characters to truncate to (default 100, 0 to disable). - */ - function sanitize($string, $force_lowercase = true, $anal = false, $trunc = 100) { - $strip = array("~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]", - "}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—", - "—", "–", ",", "<", ".", ">", "/", "?"); - $clean = trim(str_replace($strip, "", strip_tags($string))); - $clean = preg_replace('/\s+/', "-", $clean); - $clean = ($anal ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean); - $clean = ($trunc ? substr($clean, 0, $trunc) : $clean); - return ($force_lowercase) ? - (function_exists('mb_strtolower')) ? - mb_strtolower($clean, 'UTF-8') : - strtolower($clean) : - $clean; - } - - /** - * Function: trackback_respond - * Responds to a trackback request. - * - * Parameters: - * $error - Is this an error? - * $message - Message to return. - */ - function trackback_respond($error = false, $message = "") { - header("Content-Type: text/xml; charset=utf-8"); - - if ($error) { - echo '\n"; - echo "\n"; - echo "1\n"; - echo "".$message."\n"; - echo ""; - exit; - } else { - echo '\n"; - echo "\n"; - echo "0\n"; - echo ""; - } - - exit; - } - - /** - * Function: trackback_send - * Sends a trackback request. - * - * Parameters: - * $post - The post we're sending from. - * $target - The URL we're sending to. - */ - function trackback_send($post, $target) { - if (empty($target)) return false; - - $target = parse_url($target); - $title = $post->title(); - fallback($title, ucfirst($post->feather)." Post #".$post->id); - $excerpt = strip_tags(truncate($post->excerpt(), 255)); - - if (!empty($target["query"])) $target["query"] = "?".$target["query"]; - if (empty($target["port"])) $target["port"] = 80; - - $connect = fsockopen($target["host"], $target["port"]); - if (!$connect) return false; - - $config = Config::current(); - $query = "url=".rawurlencode($post->url())."&". - "title=".rawurlencode($title)."&". - "blog_name=".rawurlencode($config->name)."&". - "excerpt=".rawurlencode($excerpt); - - fwrite($connect, "POST ".$target["path"].$target["query"]." HTTP/1.1\n"); - fwrite($connect, "Host: ".$target["host"]."\n"); - fwrite($connect, "Content-type: application/x-www-form-urlencoded\n"); - fwrite($connect, "Content-length: ". strlen($query)."\n"); - fwrite($connect, "Connection: close\n\n"); - fwrite($connect, $query); - - fclose($connect); - - return true; - } - - /** - * Function: send_pingbacks - * Sends pingback requests to the URLs in a string. - * - * Parameters: - * $string - The string to crawl for pingback URLs. - * $post - The post we're sending from. - */ - function send_pingbacks($string, $post) { - foreach (grab_urls($string) as $url) - if ($ping_url = pingback_url($url)) { - require_once INCLUDES_DIR."/lib/ixr.php"; - - $client = new IXR_Client($ping_url); - $client->timeout = 3; - $client->useragent.= " -- Chyrp/".CHYRP_VERSION; - $client->query("pingback.ping", $post->url(), $url); - } - } - - /** - * Function: grab_urls - * Crawls a string for links. - * - * Parameters: - * $string - The string to crawl. - * - * Returns: - * An array of all URLs found in the string. - */ - function grab_urls($string) { - $regexp = "/]+href=[\"|']([^\"]+)[\"|']>[^<]+<\/a>/"; - preg_match_all(Trigger::current()->filter($regexp, "link_regexp"), stripslashes($string), $matches); - $matches = $matches[1]; - return $matches; - } - - /** - * Function: pingback_url - * Checks if a URL is pingback-capable. - * - * Parameters: - * $url - The URL to check. - * - * Returns: - * The pingback target, if the URL is pingback-capable. - */ - function pingback_url($url) { - extract(parse_url($url), EXTR_SKIP); - if (!isset($host)) return false; - - $path = (!isset($path)) ? '/' : $path ; - if (isset($query)) $path.= '?'.$query; - $port = (isset($port)) ? $port : 80 ; - - # Connect - $connect = @fsockopen($host, $port, $errno, $errstr, 2); - if (!$connect) return false; - - # Send the GET headers - fwrite($connect, "GET $path HTTP/1.1\r\n"); - fwrite($connect, "Host: $host\r\n"); - fwrite($connect, "User-Agent: Chyrp/".CHYRP_VERSION."\r\n\r\n"); - - # Check for X-Pingback header - $headers = ""; - while (!feof($connect)) { - $line = fgets($connect, 512); - if (trim($line) == "") break; - $headers.= trim($line)."\n"; - - if (preg_match("/X-Pingback: (.+)/i", $line, $matches)) - return trim($matches[1]); - - # Nothing's found so far, so grab the content-type - # for the search afterwards - if (preg_match("/Content-Type: (.+)/i", $headers, $matches)) - $content_type = trim($matches[1]); - } - - # No header found, check for - if (preg_match('/(image|audio|video|model)/i', $content_type)) return false; - $size = 0; - while (!feof($connect)) { - $line = fgets($connect, 1024); - if (preg_match("//i", $line, $link)) - return $link[1]; - $size += strlen($line); - if ($size > 2048) return false; - } - - fclose($connect); - - return false; - } - - /** - * Function: camelize - * Converts a given string to camel-case. - * - * Parameters: - * $string - The string to camelize. - * $keep_spaces - Whether or not to convert underscores to spaces or remove them. - * - * Returns: - * A CamelCased string. - * - * See Also: - * - */ - function camelize($string, $keep_spaces = false) { - $lower = strtolower($string); - $deunderscore = str_replace("_", " ", $lower); - $dehyphen = str_replace("-", " ", $deunderscore); - $final = ucwords($dehyphen); - - if (!$keep_spaces) - $final = str_replace(" ", "", $final); - - return $final; - } - - /** - * Function: decamelize - * Decamelizes a string. - * - * Parameters: - * $string - The string to decamelize. - * - * Returns: - * A de_camel_cased string. - * - * See Also: - * - */ - function decamelize($string) { - return strtolower(preg_replace("/([a-z])([A-Z])/", "\\1_\\2", $string)); - } - - /** - * Function: selected - * If $val1 == $val2, outputs or returns @ selected="selected"@ - * - * Parameters: - * $val1 - First value. - * $val2 - Second value. - * $return - Return @ selected="selected"@ instead of outputting it - */ - function selected($val1, $val2, $return = false) { - if ($val1 == $val2) - if ($return) - return ' selected="selected"'; - else - echo ' selected="selected"'; - } - - /** - * Function: checked - * If $val == 1 (true), outputs ' checked="checked"' - * - * Parameters: - * $val - Value to check. - */ - function checked($val) { - if ($val == 1) echo ' checked="checked"'; - } - - /** - * Function: module_enabled - * Returns whether the given module is enabled or not. - * - * Parameters: - * $name - The folder name of the module. - * - * Returns: - * Whether or not the requested module is enabled. - */ - function module_enabled($name) { - $config = Config::current(); - return in_array($name, $config->enabled_modules); - } - - /** - * Function: feather_enabled - * Returns whether the given feather is enabled or not. - * - * Parameters: - * $name - The folder name of the feather. - * - * Returns: - * Whether or not the requested feather is enabled. - */ - function feather_enabled($name) { - $config = Config::current(); - return in_array($name, $config->enabled_feathers); - } - - /** - * Function: fallback - * Sets a given variable if it is not set. - * - * The last of the arguments or the first non-empty value will be used. - * - * Parameters: - * &$variable - The variable to return or set. - * - * Returns: - * The value of whatever was chosen. - */ - function fallback(&$variable) { - if (is_bool($variable)) - return $variable; - - $set = (!isset($variable) or (is_string($variable) and trim($variable) === "") or $variable === array()); - - $args = func_get_args(); - array_shift($args); - if (count($args) > 1) { - foreach ($args as $arg) { - $fallback = $arg; - - if (isset($arg) and (!is_string($arg) or (is_string($arg) and trim($arg) !== "")) and $arg !== array()) - break; - } - } else - $fallback = isset($args[0]) ? $args[0] : null ; - - if ($set) - $variable = $fallback; - - return $set ? $fallback : $variable ; - } - - /** - * Function: oneof - * Returns the first argument that is set and non-empty. - * - * It will guess where to stop based on the types of the arguments, e.g. "" has priority over array() but not 1. - */ - function oneof() { - $last = null; - $args = func_get_args(); - foreach ($args as $index => $arg) { - if (!isset($arg) or (is_string($arg) and trim($arg) === "") or $arg === array() or (is_object($arg) and empty($arg)) or ($arg === "0000-00-00 00:00:00")) - $last = $arg; - else - return $arg; - - if ($index + 1 == count($args)) - break; - - $next = $args[$index + 1]; - - $incomparable = ((is_array($arg) and !is_array($next)) or # This is a big check but it should cover most "incomparable" cases. - (!is_array($arg) and is_array($next)) or # Using simple type comparison wouldn't work too well, for example - (is_object($arg) and !is_object($next)) or # when "" would take priority over 1 in oneof("", 1) because they're - (!is_object($arg) and is_object($next)) or # different types. - (is_resource($arg) and !is_resource($next)) or - (!is_resource($arg) and is_resource($next))); - - if (isset($arg) and isset($next) and $incomparable) - return $arg; - } - - return $last; - } - - /** - * Function: random - * Returns a random string. - * - * Parameters: - * $length - How long the string should be. - * $specialchars - Use special characters in the resulting string? - */ - function random($length, $specialchars = false) { - $pattern = "1234567890abcdefghijklmnopqrstuvwxyz"; - - if ($specialchars) - $pattern.= "!@#$%^&*()?~"; - - $len = strlen($pattern) - 1; - - $key = ""; - for($i = 0; $i < $length; $i++) - $key.= $pattern[rand(0, $len)]; - - return $key; - } - - /** - * Function: unique_filename - * Makes a given filename unique for the uploads directory. - * - * Parameters: - * $name - The name to check. - * $path - Path to check in. - * $num - Number suffix from which to start increasing if the filename exists. - * - * Returns: - * A unique version of the given $name. - */ - function unique_filename($name, $path = "", $num = 2) { - $path = rtrim($path, "/"); - if (!file_exists(MAIN_DIR.Config::current()->uploads_path.$path."/".$name)) - return $name; - - $name = explode(".", $name); - - # Handle common double extensions - foreach (array("tar.gz", "tar.bz", "tar.bz2") as $extension) { - list($first, $second) = explode(".", $extension); - $file_first =& $name[count($name) - 2]; - if ($file_first == $first and end($name) == $second) { - $file_first = $first.".".$second; - array_pop($name); - } - } - - $ext = ".".array_pop($name); - - $try = implode(".", $name)."-".$num.$ext; - if (!file_exists(MAIN_DIR.Config::current()->uploads_path.$path."/".$try)) - return $try; - - return unique_filename(implode(".", $name).$ext, $path, $num + 1); - } - - /** - * Function: upload - * Moves an uploaded file to the uploads directory. - * - * Parameters: - * $file - The $_FILES value. - * $extension - An array of valid extensions (case-insensitive). - * $path - A sub-folder in the uploads directory (optional). - * $put - Use copy() instead of move_uploaded_file()? - * - * Returns: - * The resulting filename from the upload. - */ - function upload($file, $extension = null, $path = "", $put = false) { - $file_split = explode(".", $file['name']); - $path = rtrim($path, "/"); - $dir = MAIN_DIR.Config::current()->uploads_path.$path; - - if (!file_exists($dir)) - mkdir($dir, 0777, true); - - $original_ext = end($file_split); - - # Handle common double extensions - foreach (array("tar.gz", "tar.bz", "tar.bz2") as $ext) { - list($first, $second) = explode(".", $ext); - $file_first =& $file_split[count($file_split) - 2]; - if ($file_first == $first and end($file_split) == $second) { - $file_first = $first.".".$second; - array_pop($file_split); - } - } - - $file_ext = end($file_split); - - if (is_array($extension)) { - if (!in_array(strtolower($file_ext), $extension) and !in_array(strtolower($original_ext), $extension)) { - $list = ""; - for ($i = 0; $i < count($extension); $i++) { - $comma = ""; - if (($i + 1) != count($extension)) $comma = ", "; - if (($i + 2) == count($extension)) $comma = ", and "; - $list.= "*.".$extension[$i]."".$comma; - } - error(__("Invalid Extension"), _f("Only %s files are accepted.", array($list))); - } - } elseif (isset($extension) and - strtolower($file_ext) != strtolower($extension) and - strtolower($original_ext) != strtolower($extension)) - error(__("Invalid Extension"), _f("Only %s files are supported.", array("*.".$extension))); - - array_pop($file_split); - $file_clean = implode(".", $file_split); - $file_clean = sanitize($file_clean, false).".".$file_ext; - $filename = unique_filename($file_clean, $path); - - $message = __("Couldn't upload file. CHMOD ".$dir." to 777 and try again. If this problem persists, it's probably timing out; in which case, you must contact your system administrator to increase the maximum POST and upload sizes."); - - if ($put) { - if (!@copy($file['tmp_name'], $dir."/".$filename)) - error(__("Error"), $message); - } elseif (!@move_uploaded_file($file['tmp_name'], $dir."/".$filename)) - error(__("Error"), $message); - - return ($path ? $path."/".$filename : $filename); - } - - /** - * Function: upload_from_url - * Copy a file from a specified URL to their upload directory. - * - * Parameters: - * $url - The URL to copy. - * $extension - An array of valid extensions (case-insensitive). - * $path - A sub-folder in the uploads directory (optional). - * - * See Also: - * - */ - function upload_from_url($url, $extension = null, $path = "") { - $file = tempnam(null, "chyrp"); - file_put_contents($file, get_remote($url)); - - $fake_file = array("name" => basename(parse_url($url, PHP_URL_PATH)), - "tmp_name" => $file); - - return upload($fake_file, $extension, $path, true); - } - - /** - * Function: uploaded - * Returns a URL to an uploaded file. - * - * Parameters: - * $file - Filename relative to the uploads directory. - */ - function uploaded($file, $url = true) { - if (empty($file)) - return ""; - - $config = Config::current(); - return ($url ? $config->chyrp_url.$config->uploads_path.$file : MAIN_DIR.$config->uploads_path.$file); - } - - /** - * Function: timer_start - * Starts the timer. - */ - function timer_start() { - global $time_start; - $mtime = explode(" ", microtime()); - $mtime = $mtime[1] + $mtime[0]; - $time_start = $mtime; - } - - /** - * Function: timer_stop - * Stops the timer and returns the total time. - * - * Parameters: - * $precision - Number of decimals places to round to. - * - * Returns: - * A formatted number with the given $precision. - */ - function timer_stop($precision = 3) { - global $time_start; - $mtime = microtime(); - $mtime = explode(" ", $mtime); - $mtime = $mtime[1] + $mtime[0]; - $time_end = $mtime; - $time_total = $time_end - $time_start; - return number_format($time_total, $precision); - } - - /** - * Function: normalize - * Attempts to normalize all newlines and whitespace into single spaces. - * - * Returns: - * The normalized string. - */ - function normalize($string) { - $trimmed = trim($string); - $newlines = str_replace("\n\n", " ", $trimmed); - $newlines = str_replace("\n", "", $newlines); - $normalized = preg_replace("/[\s\n\r\t]+/", " ", $newlines); - return $normalized; - } - - /** - * Function: get_remote - * Grabs the contents of a website/location. - * - * Parameters: - * $url - The URL of the location to grab. - * - * Returns: - * The response from the remote URL. - */ - function get_remote($url) { - extract(parse_url($url), EXTR_SKIP); - - if (ini_get("allow_url_fopen")) { - $content = @file_get_contents($url); - if ($http_response_header[0] != "HTTP/1.1 200 OK") - $content = "Server returned a message: $http_response_header[0]"; - } elseif (function_exists("curl_init")) { - $handle = curl_init(); - curl_setopt($handle, CURLOPT_URL, $url); - curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 1); - curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($handle, CURLOPT_TIMEOUT, 60); - $content = curl_exec($handle); - $status = curl_getinfo($handle, CURLINFO_HTTP_CODE); - curl_close($handle); - if ($status != 200) - $content = "Server returned a message: $status"; - } else { - $path = (!isset($path)) ? '/' : $path ; - if (isset($query)) $path.= '?'.$query; - $port = (isset($port)) ? $port : 80 ; - - $connect = @fsockopen($host, $port, $errno, $errstr, 2); - if (!$connect) return false; - - # Send the GET headers - fwrite($connect, "GET ".$path." HTTP/1.1\r\n"); - fwrite($connect, "Host: ".$host."\r\n"); - fwrite($connect, "User-Agent: Chyrp/".CHYRP_VERSION."\r\n\r\n"); - - $content = ""; - while (!feof($connect)) { - $line = fgets($connect, 128); - if (preg_match("/\r\n/", $line)) continue; - - $content.= $line; - } - - fclose($connect); - } - - return $content; - } - - /** - * Function: self_url - * Returns the current URL. - */ - function self_url() { - $split = explode("/", $_SERVER['SERVER_PROTOCOL']); - $protocol = strtolower($split[0]); - $default_port = ($protocol == "http") ? 80 : 443 ; - $port = ($_SERVER['SERVER_PORT'] == $default_port) ? "" : ":".$_SERVER['SERVER_PORT'] ; - return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI']; - } - - /** - * Function: show_404 - * Shows a 404 error message and immediately exits. - * - * Parameters: - * $scope - An array of values to extract into the scope. - */ - function show_404() { - header("HTTP/1.1 404 Not Found"); - - if (!defined('CHYRP_VERSION')) - exit("404 Not Found"); - - $theme = Theme::current(); - $main = MainController::current(); - - Trigger::current()->call("not_found"); - - if ($theme->file_exists("pages/404")) - $main->display("pages/404", array(), "404"); - else - error(__("404 Not Found"), __("The requested page could not be located.")); - - exit; - } - - /** - * Function: set_locale - * Set locale in a platform-independent way - * - * Parameters: - * $locale - the locale name (@en_US@, @uk_UA@, @fr_FR@ etc.) - * - * Returns: - * The encoding name used by locale-aware functions. - */ - function set_locale($locale) { # originally via http://www.onphp5.com/article/22; heavily modified - if ($locale == "en_US") return; # en_US is the default in Chyrp; their system may have - # its own locale setting and no Chyrp translation available - # for their locale, so let's just leave it alone. - - list($lang, $cty) = explode("_", $locale); - $locales = array($locale.".UTF-8", $lang, "en_US.UTF-8", "en"); - $result = setlocale(LC_ALL, $locales); - - return (!strpos($result, 'UTF-8')) ? "CP".preg_replace('~\.(\d+)$~', "\\1", $result) : "UTF-8" ; - } - - /** - * Function: sanitize_input - * Makes sure no inherently broken ideas such as magic_quotes break our application - * - * Parameters: - * $data - The array to be sanitized, usually one of @$_GET@, @$_POST@, @$_COOKIE@, or @$_REQUEST@ - */ - function sanitize_input(&$data) { - foreach ($data as &$value) - if (is_array($value)) - sanitize_input($value); - else - $value = get_magic_quotes_gpc() ? stripslashes($value) : $value ; - } - - /** - * Function: match - * Try to match a string against an array of regular expressions. - * - * Parameters: - * $try - An array of regular expressions, or a single regular expression. - * $haystack - The string to test. - * - * Returns: - * Whether or not the match succeeded. - */ - function match($try, $haystack) { - if (is_string($try)) - return (bool) preg_match($try, $haystack); - - foreach ($try as $needle) - if (preg_match($needle, $haystack)) - return true; - - return false; - } - - /** - * Function: cancel_module - * Temporarily removes a module from $config->enabled_modules. - * - * Parameters: - * $target - Module name to disable. - */ - function cancel_module($target) { - $this_disabled = array(); - - if (isset(Modules::$instances[$target])) - Modules::$instances[$target]->cancelled = true; - - $config = Config::current(); - foreach ($config->enabled_modules as $module) - if ($module != $target) - $this_disabled[] = $module; - - return $config->enabled_modules = $this_disabled; - } - - /** - * Function: time_in_timezone - * Returns the appropriate time() for representing a timezone. - */ - function time_in_timezone($timezone) { - $orig = get_timezone(); - set_timezone($timezone); - $time = date("F jS, Y, g:i A"); - set_timezone($orig); - return strtotime($time); - } - - /** - * Function: timezones - * Returns an array of timezones that have unique offsets. Doesn't count deprecated timezones. - */ - function timezones() { - $zones = array(); - - $deprecated = array("Brazil/Acre", "Brazil/DeNoronha", "Brazil/East", "Brazil/West", "Canada/Atlantic", "Canada/Central", "Canada/East-Saskatchewan", "Canada/Eastern", "Canada/Mountain", "Canada/Newfoundland", "Canada/Pacific", "Canada/Saskatchewan", "Canada/Yukon", "CET", "Chile/Continental", "Chile/EasterIsland", "CST6CDT", "Cuba", "EET", "Egypt", "Eire", "EST", "EST5EDT", "Etc/GMT", "Etc/GMT+0", "Etc/GMT+1", "Etc/GMT+10", "Etc/GMT+11", "Etc/GMT+12", "Etc/GMT+2", "Etc/GMT+3", "Etc/GMT+4", "Etc/GMT+5", "Etc/GMT+6", "Etc/GMT+7", "Etc/GMT+8", "Etc/GMT+9", "Etc/GMT-0", "Etc/GMT-1", "Etc/GMT-10", "Etc/GMT-11", "Etc/GMT-12", "Etc/GMT-13", "Etc/GMT-14", "Etc/GMT-2", "Etc/GMT-3", "Etc/GMT-4", "Etc/GMT-5", "Etc/GMT-6", "Etc/GMT-7", "Etc/GMT-8", "Etc/GMT-9", "Etc/GMT0", "Etc/Greenwich", "Etc/UCT", "Etc/Universal", "Etc/UTC", "Etc/Zulu", "Factory", "GB", "GB-Eire", "GMT", "GMT+0", "GMT-0", "GMT0", "Greenwich", "Hongkong", "HST", "Iceland", "Iran", "Israel", "Jamaica", "Japan", "Kwajalein", "Libya", "MET", "Mexico/BajaNorte", "Mexico/BajaSur", "Mexico/General", "MST", "MST7MDT", "Navajo", "NZ", "NZ-CHAT", "Poland", "Portugal", "PRC", "PST8PDT", "ROC", "ROK", "Singapore", "Turkey", "UCT", "Universal", "US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Pacific-New", "US/Samoa", "UTC", "W-SU", "WET", "Zulu"); - - foreach (timezone_identifiers_list() as $zone) - if (!in_array($zone, $deprecated)) - $zones[] = array("name" => $zone, - "now" => time_in_timezone($zone)); - - function by_time($a, $b) { - return (int) ($a["now"] > $b["now"]); - } - - usort($zones, "by_time"); - - return $zones; - } - - /** - * Function: set_timezone - * Sets the timezone. - * - * Parameters: - * $timezone - The timezone to set. - */ - function set_timezone($timezone) { - if (function_exists("date_default_timezone_set")) - date_default_timezone_set($timezone); - else - ini_set("date.timezone", $timezone); - } - - /** - * Function: get_timezone() - * Returns the current timezone. - */ - function get_timezone() { - if (function_exists("date_default_timezone_set")) - return date_default_timezone_get(); - else - return ini_get("date.timezone"); - } - - /** - * Function: error_panicker - * Exits and states where the error occurred. - */ - function error_panicker($errno, $message, $file, $line) { - if (error_reporting() === 0) - return; # Suppressed error. - - exit("ERROR: ".$message." (".$file." on line ".$line.")"); - } - - /** - * Function: keywords - * Handle keyword-searching. - * - * Parameters: - * $query - The query to parse. - * $plain - WHERE syntax to search for non-keyword queries. - * $table - If specified, the keywords will be checked against this table's columns for validity. - * - * Returns: - * An array containing the "WHERE" queries and the corresponding parameters. - */ - function keywords($query, $plain, $table = null) { - if (!trim($query)) - return array(array(), array()); - - $search = array(); - $matches = array(); - $where = array(); - $params = array(); - - if ($table) - $columns = SQL::current()->select($table)->fetch(); - - $queries = explode(" ", $query); - foreach ($queries as $query) - if (!preg_match("/([a-z0-9_]+):(.+)/", $query)) - $search[] = $query; - else - $matches[] = $query; - - $times = array("year", "month", "day", "hour", "minute", "second"); - - foreach ($matches as $match) { - list($test, $equals,) = explode(":", $match); - - if ($equals[0] == '"') { - if (substr($equals, -1) != '"') - foreach ($search as $index => $part) { - $equals.= " ".$part; - - unset($search[$index]); - - if (substr($part, -1) == '"') - break; - } - - $equals = ltrim(trim($equals, '"'), '"'); - } - - if (in_array($test, $times)) { - if ($equals == "today") - $where["created_at like"] = date("%Y-m-d %"); - elseif ($equals == "yesterday") - $where["created_at like"] = date("%Y-m-d %", now("-1 day")); - elseif ($equals == "tomorrow") - error(__("Error"), "Unfortunately our flux capacitor is currently having issues. Try again yesterday."); - else - $where[strtoupper($test)."(created_at)"] = $equals; - } elseif ($test == "author") { - $user = new User(array("login" => $equals)); - if ($user->no_results and $equals == "me") { - !($table == "users") ? $where["user_id"] = Visitor::current()->id : $where["id"] = Visitor::current()->id; - } else - !($table == "users") ? $where["user_id"] = $user->id : $where["id"] = $user->id; - } elseif ($test == "group") { - $group = new Group(array("name" => $equals)); - $where["group_id"] = $equals = ($group->no_results) ? 0 : $group->id; - } else - $where[$test] = $equals; - } - - if ($table) - foreach ($where as $col => $val) - if (!isset($where[$col])) { - if ($table == "posts") { - $where["post_attributes.name"] = $col; - $where["post_attributes.value like"] = "%".$val."%"; - } - - unset($where[$col]); - } - - if (!empty($search)) { - $where[] = $plain; - $params[":query"] = "%".join(" ", $search)."%"; - } - - $keywords = array($where, $params); - - Trigger::current()->filter($keywords, "keyword_search", $query, $plain); - - return $keywords; - } - - /** - * Function: init_extensions - * Initialize all Modules and Feathers. - */ - function init_extensions() { - $config = Config::current(); - - # Instantiate all Modules. - foreach ($config->enabled_modules as $index => $module) { - if (!file_exists(MODULES_DIR."/".$module."/".$module.".php")) { - unset($config->enabled_modules[$index]); - continue; - } - - if (file_exists(MODULES_DIR."/".$module."/locale/".$config->locale.".mo")) - load_translator($module, MODULES_DIR."/".$module."/locale/".$config->locale.".mo"); - - require MODULES_DIR."/".$module."/".$module.".php"; - - $camelized = camelize($module); - if (!class_exists($camelized)) - continue; - - Modules::$instances[$module] = new $camelized; - Modules::$instances[$module]->safename = $module; - - foreach (YAML::load(MODULES_DIR."/".$module."/info.yaml") as $key => $val) - Modules::$instances[$module]->$key = (is_string($val)) ? __($val, $module) : $val ; - } - - # Instantiate all Feathers. - foreach ($config->enabled_feathers as $index => $feather) { - if (!file_exists(FEATHERS_DIR."/".$feather."/".$feather.".php")) { - unset($config->enabled_feathers[$index]); - continue; - } - - if (file_exists(FEATHERS_DIR."/".$feather."/locale/".$config->locale.".mo")) - load_translator($feather, FEATHERS_DIR."/".$feather."/locale/".$config->locale.".mo"); - - require FEATHERS_DIR."/".$feather."/".$feather.".php"; - - $camelized = camelize($feather); - if (!class_exists($camelized)) - continue; - - Feathers::$instances[$feather] = new $camelized; - Feathers::$instances[$feather]->safename = $feather; - - foreach (YAML::load(FEATHERS_DIR."/".$feather."/info.yaml") as $key => $val) - Feathers::$instances[$feather]->$key = (is_string($val)) ? __($val, $feather) : $val ; - } - - # Initialize all modules. - foreach (Feathers::$instances as $feather) - if (method_exists($feather, "__init")) - $feather->__init(); - - foreach (Modules::$instances as $module) - if (method_exists($module, "__init")) - $module->__init(); - } - - /** - * Function: xml2arr - * Recursively converts a SimpleXML object (and children) to an array. - * - * Parameters: - * $parse - The SimpleXML object to convert into an array. - */ - function xml2arr($parse) { - if (empty($parse)) - return ""; - - $parse = (array) $parse; - - foreach ($parse as &$val) - if (get_class($val) == "SimpleXMLElement") - $val = xml2arr($val); - - return $parse; - } - - /** - * Function: arr2xml - * Recursively adds an array (or object I guess) to a SimpleXML object. - * - * Parameters: - * &$object - The SimpleXML object to modify. - * $data - The data to add to the SimpleXML object. - */ - function arr2xml(&$object, $data) { - foreach ($data as $key => $val) { - if (is_int($key) and (empty($val) or (is_string($val) and trim($val) == ""))) { - unset($data[$key]); - continue; - } - - if (is_array($val)) { - if (in_array(0, array_keys($val))) { # Numeric-indexed things need to be added as duplicates - foreach ($val as $dup) { - $xml = $object->addChild($key); - arr2xml($xml, $dup); - } - } else { - $xml = $object->addChild($key); - arr2xml($xml, $val); - } - } else - $object->addChild($key, fix($val, false, false)); - } - } - - /** - * Function: relative_time - * Returns the difference between the given timestamps or now. - * - * Parameters: - * $time - Timestamp to compare to. - * $from - Timestamp to compare from. If not specified, defaults to now. - * - * Returns: - * A string formatted like "3 days ago" or "3 days from now". - */ - function relative_time($when, $from = null) { - fallback($from, time()); - - $time = (is_numeric($when)) ? $when : strtotime($when) ; - - $difference = $from - $time; - - if ($difference < 0) { - $word = "from now"; - $difference = -$difference; - } elseif ($difference > 0) - $word = "ago"; - else - return "just now"; - - $units = array("second" => 1, - "minute" => 60, - "hour" => 60 * 60, - "day" => 60 * 60 * 24, - "week" => 60 * 60 * 24 * 7, - "month" => 60 * 60 * 24 * 30, - "year" => 60 * 60 * 24 * 365, - "decade" => 60 * 60 * 24 * 365 * 10, - "century" => 60 * 60 * 24 * 365 * 100, - "millennium" => 60 * 60 * 24 * 365 * 1000); - - $possible_units = array(); - foreach ($units as $name => $val) - if (($name == "week" and $difference >= ($val * 2)) or # Only say "weeks" after two have passed. - ($name != "week" and $difference >= $val)) - $unit = $possible_units[] = $name; - - $precision = (int) in_array("year", $possible_units); - $amount = round($difference / $units[$unit], $precision); - - return $amount." ".pluralize($unit, $amount)." ".$word; - } - - /** - * Function: list_notate - * Notates an array as a list of things. - * - * Parameters: - * $array - An array of things to notate. - * $quotes - Wrap quotes around strings? - * - * Returns: - * A string like "foo, bar, and baz". - */ - function list_notate($array, $quotes = false) { - $count = 0; - $items = array(); - foreach ($array as $item) { - $string = (is_string($item) and $quotes) ? "“".$item."”" : $item ; - if (count($array) == ++$count and $count !== 1) - $items[] = __("and ").$string; - else - $items[] = $string; - } - - return (count($array) == 2) ? implode(" ", $items) : implode(", ", $items) ; - } - - /** - * Function: email - * Send an email. Function arguments are exactly the same as the PHP mail() function. - * - * This is intended so that modules can provide an email method if the server cannot use mail(). - */ - function email() { - $function = "mail"; - Trigger::current()->filter($function, "send_mail"); - $args = func_get_args(); # Looks redundant, but it must be so in order to meet PHP's retardation requirements. - return call_user_func_array($function, $args); - } - - /** - * Function: now - * Alias to strtotime, for prettiness like now("+1 day"). - */ - function now($when) { - return strtotime($when); - } - - /** - * Function: comma_sep - * Convert a comma-seperated string into an array of the listed values. - */ - function comma_sep($string) { - $commas = explode(",", $string); - $trimmed = array_map("trim", $commas); - $cleaned = array_diff(array_unique($trimmed), array("")); - return $cleaned; - } diff --git a/News/includes/interface/Feather.php b/News/includes/interface/Feather.php deleted file mode 100644 index 48a4068..0000000 --- a/News/includes/interface/Feather.php +++ /dev/null @@ -1,40 +0,0 @@ - object created. - */ - public function submit(); - - /** - * Function: update - * Handles updating a post. - */ - public function update($post); - - /** - * Function: title - * Returns the appropriate source to be treated as a "title" of a post. - * If there is no immediate solution, you may use . - */ - public function title($post); - - /** - * Function: excerpt - * Returns the appropriate source, unmodified, to be used as an excerpt of a post. - */ - public function excerpt($post); - - /** - * Function: feed_content - * Returns the appropriate content for a feed. - */ - public function feed_content($post); - } diff --git a/News/includes/javascript.php b/News/includes/javascript.php deleted file mode 100755 index 5d1518b..0000000 --- a/News/includes/javascript.php +++ /dev/null @@ -1,143 +0,0 @@ - - diff --git a/News/includes/lib/PasswordHash.php b/News/includes/lib/PasswordHash.php deleted file mode 100755 index 6b52212..0000000 --- a/News/includes/lib/PasswordHash.php +++ /dev/null @@ -1,236 +0,0 @@ - in 2004-2006 and placed in -# the public domain. Revised in subsequent years, still public domain. -# -# The homepage URL for this framework is: http://www.openwall.com/phpass/ -# -class PasswordHash { - var $itoa64; - var $iteration_count_log2; - var $portable_hashes; - var $random_state; - - function PasswordHash($iteration_count_log2, $portable_hashes) - { - $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - - if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) - $iteration_count_log2 = 8; - $this->iteration_count_log2 = $iteration_count_log2; - - $this->portable_hashes = $portable_hashes; - - $this->random_state = microtime() . uniqid(rand(), TRUE); // removed getmypid() for compability reasons; - } - - function get_random_bytes($count) - { - $output = ''; - if (@is_readable('/dev/urandom') && - ($fh = @fopen('/dev/urandom', 'rb'))) { - $output = fread($fh, $count); - fclose($fh); - } - - if (strlen($output) < $count) { - $output = ''; - for ($i = 0; $i < $count; $i += 16) { - $this->random_state = - md5(microtime() . $this->random_state); - $output .= - pack('H*', md5($this->random_state)); - } - $output = substr($output, 0, $count); - } - - return $output; - } - - function encode64($input, $count) - { - $output = ''; - $i = 0; - do { - $value = ord($input[$i++]); - $output .= $this->itoa64[$value & 0x3f]; - if ($i < $count) - $value |= ord($input[$i]) << 8; - $output .= $this->itoa64[($value >> 6) & 0x3f]; - if ($i++ >= $count) - break; - if ($i < $count) - $value |= ord($input[$i]) << 16; - $output .= $this->itoa64[($value >> 12) & 0x3f]; - if ($i++ >= $count) - break; - $output .= $this->itoa64[($value >> 18) & 0x3f]; - } while ($i < $count); - - return $output; - } - - function gensalt_private($input) - { - $output = '$P$'; - $output .= $this->itoa64[min($this->iteration_count_log2 + - ((PHP_VERSION >= '5') ? 5 : 3), 30)]; - $output .= $this->encode64($input, 6); - - return $output; - } - - function crypt_private($password, $setting) - { - $output = '*0'; - if (substr($setting, 0, 2) == $output) - $output = '*1'; - - $id = substr($setting, 0, 3); - # We use "$P$", phpBB3 uses "$H$" for the same thing - if ($id != '$P$' && $id != '$H$') - return $output; - - $count_log2 = strpos($this->itoa64, $setting[3]); - if ($count_log2 < 7 || $count_log2 > 30) - return $output; - - $count = 1 << $count_log2; - - $salt = substr($setting, 4, 8); - if (strlen($salt) != 8) - return $output; - - # We're kind of forced to use MD5 here since it's the only - # cryptographic primitive available in all versions of PHP - # currently in use. To implement our own low-level crypto - # in PHP would result in much worse performance and - # consequently in lower iteration counts and hashes that are - # quicker to crack (by non-PHP code). - if (PHP_VERSION >= '5') { - $hash = md5($salt . $password, TRUE); - do { - $hash = md5($hash . $password, TRUE); - } while (--$count); - } else { - $hash = pack('H*', md5($salt . $password)); - do { - $hash = pack('H*', md5($hash . $password)); - } while (--$count); - } - - $output = substr($setting, 0, 12); - $output .= $this->encode64($hash, 16); - - return $output; - } - - function gensalt_extended($input) - { - $count_log2 = min($this->iteration_count_log2 + 8, 24); - # This should be odd to not reveal weak DES keys, and the - # maximum valid value is (2**24 - 1) which is odd anyway. - $count = (1 << $count_log2) - 1; - - $output = '_'; - $output .= $this->itoa64[$count & 0x3f]; - $output .= $this->itoa64[($count >> 6) & 0x3f]; - $output .= $this->itoa64[($count >> 12) & 0x3f]; - $output .= $this->itoa64[($count >> 18) & 0x3f]; - - $output .= $this->encode64($input, 3); - - return $output; - } - - function gensalt_blowfish($input) - { - # This one needs to use a different order of characters and a - # different encoding scheme from the one in encode64() above. - # We care because the last character in our encoded string will - # only represent 2 bits. While two known implementations of - # bcrypt will happily accept and correct a salt string which - # has the 4 unused bits set to non-zero, we do not want to take - # chances and we also do not want to waste an additional byte - # of entropy. - $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - - $output = '$2a$'; - $output .= chr(ord('0') + $this->iteration_count_log2 / 10); - $output .= chr(ord('0') + $this->iteration_count_log2 % 10); - $output .= '$'; - - $i = 0; - do { - $c1 = ord($input[$i++]); - $output .= $itoa64[$c1 >> 2]; - $c1 = ($c1 & 0x03) << 4; - if ($i >= 16) { - $output .= $itoa64[$c1]; - break; - } - - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 4; - $output .= $itoa64[$c1]; - $c1 = ($c2 & 0x0f) << 2; - - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 6; - $output .= $itoa64[$c1]; - $output .= $itoa64[$c2 & 0x3f]; - } while (1); - - return $output; - } - - function HashPassword($password) - { - $random = ''; - - if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) { - $random = $this->get_random_bytes(16); - $hash = - crypt($password, $this->gensalt_blowfish($random)); - if (strlen($hash) == 60) - return $hash; - } - - if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) { - if (strlen($random) < 3) - $random = $this->get_random_bytes(3); - $hash = - crypt($password, $this->gensalt_extended($random)); - if (strlen($hash) == 20) - return $hash; - } - - if (strlen($random) < 6) - $random = $this->get_random_bytes(6); - $hash = - $this->crypt_private($password, - $this->gensalt_private($random)); - if (strlen($hash) == 34) - return $hash; - - # Returning '*' on error is safe here, but would _not_ be safe - # in a crypt(3)-like function used _both_ for generating new - # hashes and for validating passwords against existing hashes. - return '*'; - } - - function CheckPassword($password, $stored_hash) - { - $hash = $this->crypt_private($password, $stored_hash); - if ($hash[0] == '*') - $hash = crypt($password, $stored_hash); - - return $hash == $stored_hash; - } -} - -?> diff --git a/News/includes/lib/YAML.php b/News/includes/lib/YAML.php deleted file mode 100644 index 2727d89..0000000 --- a/News/includes/lib/YAML.php +++ /dev/null @@ -1,154 +0,0 @@ -parse($line); - } - - return $loader->toArray(); - } - - /** - * Load a file containing YAML and parse it into a PHP array. - * - * If the file cannot be opened, an exception is thrown. If the - * file is read but parsing fails, an empty array is returned. - * - * @param string $filename Filename to load - * @return array PHP array representation of YAML content - * @throws IllegalArgumentException If $filename is invalid - * @throws Horde_Yaml_Exception If the file cannot be opened. - */ - public static function loadFile($filename) - { - if (!is_string($filename) || !strlen($filename)) { - $msg = 'Filename must be a string and cannot be empty'; - throw new InvalidArgumentException($msg); - } - - $stream = @fopen($filename, 'rb'); - if (!$stream) { - throw new Horde_Yaml_Exception('Failed to open file: ', error_get_last()); - } - - return self::loadStream($stream); - } - - /** - * Load YAML from a PHP stream resource. - * - * @param resource $stream PHP stream resource - * @return array PHP array representation of YAML content - */ - public static function loadStream($stream) - { - if (! is_resource($stream) || get_resource_type($stream) != 'stream') { - throw new InvalidArgumentException('Stream must be a stream resource'); - } - - if (is_callable(self::$loadfunc)) { - $array = call_user_func(self::$loadfunc, stream_get_contents($stream)); - return is_array($array) ? $array : array(); - } - - $loader = new Horde_Yaml_Loader; - while (!feof($stream)) { - $loader->parse(stream_get_line($stream, 100000, "\n")); - } - - return $loader->toArray(); - } - - /** - * Dump a PHP array to YAML. - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. - * - * @param array|Traversable $array PHP array or traversable object - * @param integer $options Options to pass to dumper - * @return string YAML representation of $value - */ - public static function dump($value, $options = array()) - { - $dumper = new Horde_Yaml_Dumper; - return $dumper->dump($value, $options); - } - -} diff --git a/News/includes/lib/YAML/Dumper.php b/News/includes/lib/YAML/Dumper.php deleted file mode 100644 index 43d07f4..0000000 --- a/News/includes/lib/YAML/Dumper.php +++ /dev/null @@ -1,213 +0,0 @@ - 2, - 'wordwrap' => 0); - $this->_options = array_merge($defaults, $options); - - if (! is_int($this->_options['indent'])) { - throw new InvalidArgumentException('Indent must be an integer'); - } - - if (! is_int($this->_options['wordwrap'])) { - throw new InvalidArgumentException('Wordwrap column must be an integer'); - } - - // new YAML document - $dump = "---\n"; - - // iterate through array and yamlize it - foreach ($value as $key => $val) { - $dump .= $this->_yamlize($key, $val, 0, ($value === array_values($value))); - } - return $dump; - } - - /** - * Attempts to convert a key / value array item to YAML - * - * @param string $key The name of the key - * @param string|array $value The value of the item - * @param integer $indent The indent of the current node - * @param boolean $seq Is the item part of a sequence? - * @return string - */ - protected function _yamlize($key, $value, $indent, $seq = false) - { - if ($value instanceof Serializable) { - // Dump serializable objects as !php/object::classname serialize_data - $data = '!php/object::' . get_class($value) . ' ' . $value->serialize(); - $string = $this->_dumpNode($key, $data, $indent); - } elseif (is_array($value) || $value instanceof Traversable) { - // It has children. Make it the right kind of item. - $string = $this->_dumpNode($key, null, $indent); - - // Add the indent. - $indent += $this->_options['indent']; - - // Yamlize the array. - $string .= $this->_yamlizeArray($value, $indent); - } elseif (!is_array($value)) { - // No children. - $string = $this->_dumpNode($key, $value, $indent, $seq); - } - - return $string; - } - - /** - * Attempts to convert an array to YAML - * - * @param array $array The array you want to convert - * @param integer $indent The indent of the current level - * @return string - */ - protected function _yamlizeArray($array, $indent) - { - if (!is_array($array)) { - return false; - } - - $seq = ($array === array_values($array)); - - $string = ''; - foreach ($array as $key => $value) { - $string .= $this->_yamlize($key, $value, $indent, $seq); - } - return $string; - } - - /** - * Returns YAML from a key and a value - * - * @param string $key The name of the key - * @param string $value The value of the item - * @param integer $indent The indent of the current node - * @param boolean $seq Is the item part of a sequence? - * @return string - */ - protected function _dumpNode($key, $value, $indent, $seq = false) - { - // Do some folding here, for blocks. - if (strpos($value, "\n") !== false - || strpos($value, ': ') !== false - || strpos($value, '- ') !== false) { - $value = $this->_doLiteralBlock($value, $indent); - } else { - $value = $this->_fold($value, $indent); - } - - if (is_bool($value)) { - $value = ($value) ? 'true' : 'false'; - } elseif (is_float($value)) { - if (is_nan($value)) { - $value = '.NAN'; - } elseif ($value === INF) { - $value = '.INF'; - } elseif ($value === -INF) { - $value = '-.INF'; - } - } - - $spaces = str_repeat(' ', $indent); - - if ($seq) { - // It's a sequence. - $string = $spaces . '- ' . $value . "\n"; - } else { - // It's mapped. - $string = $spaces . $key . ': ' . $value . "\n"; - } - - return $string; - } - - /** - * Creates a literal block for dumping - * - * @param string $value - * @param integer $indent The value of the indent. - * @return string - */ - protected function _doLiteralBlock($value, $indent) - { - $exploded = explode("\n", $value); - $newValue = '|'; - $indent += $this->_options['indent']; - $spaces = str_repeat(' ', $indent); - foreach ($exploded as $line) { - $newValue .= "\n" . $spaces . trim($line); - } - return $newValue; - } - - /** - * Folds a string of text, if necessary - * - * @param $value The string you wish to fold - * @return string - */ - protected function _fold($value, $indent) - { - // Don't do anything if wordwrap is set to 0 - if (! $this->_options['wordwrap']) { - return (is_string($value) and !is_numeric($value) and !empty($value)) ? '"'.str_replace("\"", "\\\"", $value).'"' : $value ; - } - - if (strlen($value) > $this->_options['wordwrap']) { - $indent += $this->_options['indent']; - $indent = str_repeat(' ', $indent); - $wrapped = wordwrap($value, $this->_options['wordwrap'], "\n$indent"); - $value = ">\n" . $indent . $wrapped; - } - - return $value; - } - -} diff --git a/News/includes/lib/YAML/Exception.php b/News/includes/lib/YAML/Exception.php deleted file mode 100644 index 3f232ae..0000000 --- a/News/includes/lib/YAML/Exception.php +++ /dev/null @@ -1,45 +0,0 @@ -file = $code_or_lasterror['file']; - $this->line = $code_or_lasterror['line']; - $code = $code_or_lasterror['type']; - } else { - $code = $code_or_lasterror; - } - - parent::__construct($message, $code); - } - -} diff --git a/News/includes/lib/YAML/Loader.php b/News/includes/lib/YAML/Loader.php deleted file mode 100644 index 15cd08d..0000000 --- a/News/includes/lib/YAML/Loader.php +++ /dev/null @@ -1,751 +0,0 @@ -_nodeId++); - $base->indent = 0; - $this->_lastNode = $base->id; - } - - /** - * Return the PHP built from all YAML parsed so far. - * - * @return array PHP version of parsed YAML - */ - public function toArray() - { - // Here we travel through node-space and pick out references - // (& and *). - $this->_linkReferences(); - - // Build the PHP array out of node-space. - return $this->_buildArray(); - } - - /** - * Parse a line of a YAML file. - * - * @param string $line The line of YAML to parse. - * @return Horde_Yaml_Node YAML Node - */ - public function parse($line) - { - // Keep track of how many lines we've parsed for friendlier - // error messages. - ++$this->_lineNumber; - - $trimmed = trim($line); - - // If the line starts with a tab (instead of a space), throw a fit. - if (preg_match('/^ *(\t) *[^\t ]/', $line)) { - $msg = "Line {$this->_lineNumber} indent contains a tab. " - . 'YAML only allows spaces for indentation.'; - throw new Horde_Yaml_Exception($msg); - } - - if (!$this->_inBlock && empty($trimmed)) { - return; - } elseif ($this->_inBlock && empty($trimmed)) { - $last =& $this->_allNodes[$this->_lastNode]; - $last->data[key($last->data)] .= "\n"; - } elseif ($trimmed[0] != '#' && substr($trimmed, 0, 3) != '---') { - // Create a new node and get its indent - $node = new Horde_Yaml_Node($this->_nodeId++); - $node->indent = $this->_getIndent($line); - - // Check where the node lies in the hierarchy - if ($this->_lastIndent == $node->indent) { - // If we're in a block, add the text to the parent's data - if ($this->_inBlock) { - $parent =& $this->_allNodes[$this->_lastNode]; - $parent->data[key($parent->data)] .= trim($line) . $this->_blockEnd; - } else { - // The current node's parent is the same as the previous node's - if (isset($this->_allNodes[$this->_lastNode])) { - $node->parent = $this->_allNodes[$this->_lastNode]->parent; - } - } - } elseif ($this->_lastIndent < $node->indent) { - if ($this->_inBlock) { - $parent =& $this->_allNodes[$this->_lastNode]; - $parent->data[key($parent->data)] .= trim($line) . $this->_blockEnd; - } elseif (!$this->_inBlock) { - // The current node's parent is the previous node - $node->parent = $this->_lastNode; - - // If the value of the last node's data was > or | - // we need to start blocking i.e. taking in all - // lines as a text value until we drop our indent. - $parent =& $this->_allNodes[$node->parent]; - $this->_allNodes[$node->parent]->children = true; - if (is_array($parent->data)) { - if (isset($parent->data[key($parent->data)])) { - $chk = $parent->data[key($parent->data)]; - if ($chk === '>') { - $this->_inBlock = true; - $this->_blockEnd = ''; - $parent->data[key($parent->data)] = - str_replace('>', '', $parent->data[key($parent->data)]); - $parent->data[key($parent->data)] .= trim($line) . ' '; - $this->_allNodes[$node->parent]->children = false; - $this->_lastIndent = $node->indent; - } elseif ($chk === '|') { - $this->_inBlock = true; - $this->_blockEnd = "\n"; - $parent->data[key($parent->data)] = - str_replace('|', '', $parent->data[key($parent->data)]); - $parent->data[key($parent->data)] .= trim($line) . "\n"; - $this->_allNodes[$node->parent]->children = false; - $this->_lastIndent = $node->indent; - } - } - } - } - } elseif ($this->_lastIndent > $node->indent) { - // Any block we had going is dead now - if ($this->_inBlock) { - $this->_inBlock = false; - if ($this->_blockEnd == "\n") { - $last =& $this->_allNodes[$this->_lastNode]; - $last->data[key($last->data)] = - trim($last->data[key($last->data)]); - } - } - - // We don't know the parent of the node so we have to - // find it - foreach ($this->_indentSort[$node->indent] as $n) { - if ($n->indent == $node->indent) { - $node->parent = $n->parent; - } - } - } - - if (!$this->_inBlock) { - // Set these properties with information from our - // current node - $this->_lastIndent = $node->indent; - - // Set the last node - $this->_lastNode = $node->id; - - // Parse the YAML line and return its data - $node->data = $this->_parseLine($line); - - // Add the node to the master list - $this->_allNodes[$node->id] = $node; - - // Add a reference to the parent list - $this->_allParent[intval($node->parent)][] = $node->id; - - // Add a reference to the node in an indent array - $this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id]; - - // Add a reference to the node in a References array - // if this node has a YAML reference in it. - $is_array = is_array($node->data); - $key = key($node->data); - $isset = isset($node->data[$key]); - if ($isset) { - $nodeval = $node->data[$key]; - } - if (($is_array && $isset && !is_array($nodeval) && !is_object($nodeval)) - && (strlen($nodeval) && (false))) { # $nodeval[0] == '&' || $nodeval[0] == '*') && $nodeval[1] != ' ')) { - $this->_haveRefs[] =& $this->_allNodes[$node->id]; - } elseif ($is_array && $isset && is_array($nodeval)) { - // Incomplete reference making code. Needs to be - // cleaned up. - foreach ($node->data[$key] as $d) { - if (!is_array($d) && strlen($d) && (false)) { # ($d[0] == '&' || $d[0] == '*') && $d[1] != ' ')) { - $this->_haveRefs[] =& $this->_allNodes[$node->id]; - } - } - } - } - } - } - - /** - * Finds and returns the indentation of a YAML line - * - * @param string $line A line from the YAML file - * @return int Indentation level - */ - protected function _getIndent($line) - { - if (preg_match('/^\s+/', $line, $match)) { - return strlen($match[0]); - } else { - return 0; - } - } - - /** - * Parses YAML code and returns an array for a node - * - * @param string $line A line from the YAML file - * @return array - */ - protected function _parseLine($line) - { - $array = array(); - - $line = trim($line); - if (preg_match('/^-(.*):$/', $line)) { - // It's a mapped sequence - $key = trim(substr(substr($line, 1), 0, -1)); - $array[$key] = ''; - } elseif ($line[0] == '-' && substr($line, 0, 3) != '---') { - // It's a list item but not a new stream - if (strlen($line) > 1) { - // Set the type of the value. Int, string, etc - $array[] = $this->_toType(trim(substr($line, 1))); - } else { - $array[] = array(); - } - } elseif (preg_match('/^(.+):/', $line, $key)) { - // It's a key/value pair most likely - // If the key is in double quotes pull it out - if (preg_match('/^(["\'](.*)["\'](\s)*:)/', $line, $matches)) { - $value = trim(str_replace($matches[1], '', $line)); - $key = $matches[2]; - } else { - // Do some guesswork as to the key and the value - $explode = explode(':', $line); - $key = trim(array_shift($explode)); - $value = trim(implode(':', $explode)); - } - - // Set the type of the value. Int, string, etc - $value = $this->_toType($value); - if (empty($key)) { - $array[] = $value; - } else { - $array[$key] = $value; - } - } - - return $array; - } - - /** - * Finds the type of the passed value, returns the value as the new type. - * - * @param string $value - * @return mixed - */ - protected function _toType($value) - { - // Check for PHP specials - self::_unserialize($value); - if (!is_scalar($value)) { - return $value; - } - - // Used in a lot of cases. - $lower_value = strtolower($value); - - if (preg_match('/^("(.*)"|\'(.*)\')/', $value, $matches)) { - $value = (string)str_replace(array('\'\'', '\\\''), "'", end($matches)); - $value = str_replace('\\"', '"', $value); - } elseif (preg_match('/^\\[(\s*)\\]$/', $value)) { - // empty inline mapping - $value = array(); - } elseif (preg_match('/^\\[(.+)\\]$/', $value, $matches)) { - // Inline Sequence - - // Take out strings sequences and mappings - $explode = $this->_inlineEscape($matches[1]); - - // Propogate value array - $value = array(); - foreach ($explode as $v) { - $value[] = $this->_toType($v); - } - } elseif (preg_match('/^\\{(\s*)\\}$/', $value)) { - // empty inline mapping - $value = array(); - } elseif (strpos($value, ': ') !== false && !preg_match('/^{(.+)/', $value)) { - // inline mapping - $array = explode(': ', $value); - $key = trim($array[0]); - array_shift($array); - $value = trim(implode(': ', $array)); - $value = $this->_toType($value); - $value = array($key => $value); - } elseif (preg_match("/{(.+)}$/", $value, $matches)) { - // Inline Mapping - - // Take out strings sequences and mappings - $explode = $this->_inlineEscape($matches[1]); - - // Propogate value array - $array = array(); - foreach ($explode as $v) { - $array = $array + $this->_toType($v); - } - $value = $array; - } elseif ($lower_value == 'null' || $value == '' || $value == '~') { - $value = null; - } elseif ($lower_value == '.nan') { - $value = NAN; - } elseif ($lower_value == '.inf') { - $value = INF; - } elseif ($lower_value == '-.inf') { - $value = -INF; - } elseif (is_numeric($value) and !substr_count($value, ".")) { - $value = (int)$value; - } elseif (in_array($lower_value, - array('true', 'on', '+', 'yes', 'y'))) { - $value = true; - } elseif (in_array($lower_value, - array('false', 'off', '-', 'no', 'n'))) { - $value = false; - } elseif (is_numeric($value)) { - $value = (float)$value; - } else { - // Just a normal string, right? - if (($pos = strpos($value, '#')) !== false) { - $value = substr($value, 0, $pos); - } - $value = trim($value); - } - - return $value; - } - - /** - * Handle PHP serialized data. - * - * @param string &$data Data to check for serialized PHP types. - */ - protected function _unserialize(&$data) - { - if (substr($data, 0, 5) != '!php/') { - return; - } - - $first_space = strpos($data, ' '); - $type = substr($data, 5, $first_space - 5); - $class = null; - if (strpos($type, '::') !== false) { - list($type, $class) = explode('::', $type); - - if (!in_array($class, Horde_Yaml::$allowedClasses)) { - throw new Horde_Yaml_Exception("$class is not in the list of allowed classes"); - } - } - - switch ($type) { - case 'object': - if (!class_exists($class)) { - throw new Horde_Yaml_Exception("$class is not defined"); - } - - $reflector = new ReflectionClass($class); - if (!$reflector->implementsInterface('Serializable')) { - throw new Horde_Yaml_Exception("$class does not implement Serializable"); - } - - $class_data = substr($data, $first_space + 1); - $serialized = 'C:' . strlen($class) . ':"' . $class . '":' . strlen($class_data) . ':{' . $class_data . '}'; - $data = unserialize($serialized); - break; - - case 'array': - case 'hash': - $array_data = substr($data, $first_space + 1); - $array_data = Horde_Yaml::load('a: ' . $array_data); - - if (is_null($class)) { - $data = $array_data['a']; - } else { - if (!class_exists($class)) { - throw new Horde_Yaml_Exception("$class is not defined"); - } - - $array = new $class; - if (!$array instanceof ArrayAccess) { - throw new Horde_Yaml_Exception("$class does not implement ArrayAccess"); - } - - foreach ($array_data['a'] as $key => $val) { - $array[$key] = $val; - } - - $data = $array; - } - break; - } - } - - /** - * Used in inlines to check for more inlines or quoted strings - * - * @todo There should be a cleaner way to do this. While - * pure sequences seem to be nesting just fine, - * pure mappings and mappings with sequences inside - * can't go very deep. This needs to be fixed. - * - * @param string $inline Inline data - * @return array - */ - protected function _inlineEscape($inline) - { - $saved_strings = array(); - - // Check for strings - $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; - if (preg_match_all($regex, $inline, $strings)) { - $saved_strings = $strings[0]; - $inline = preg_replace($regex, 'YAMLString', $inline); - } - - // Check for sequences - if (preg_match_all('/\[(.+)\]/U', $inline, $seqs)) { - $inline = preg_replace('/\[(.+)\]/U', 'YAMLSeq', $inline); - $seqs = $seqs[0]; - } - - // Check for mappings - if (preg_match_all('/{(.+)}/U', $inline, $maps)) { - $inline = preg_replace('/{(.+)}/U', 'YAMLMap', $inline); - $maps = $maps[0]; - } - - $explode = explode(', ', $inline); - - // Re-add the sequences - if (!empty($seqs)) { - $i = 0; - foreach ($explode as $key => $value) { - if (strpos($value, 'YAMLSeq') !== false) { - $explode[$key] = str_replace('YAMLSeq', $seqs[$i], $value); - ++$i; - } - } - } - - // Re-add the mappings - if (!empty($maps)) { - $i = 0; - foreach ($explode as $key => $value) { - if (strpos($value, 'YAMLMap') !== false) { - $explode[$key] = str_replace('YAMLMap', $maps[$i], $value); - ++$i; - } - } - } - - // Re-add the strings - if (!empty($saved_strings)) { - $i = 0; - foreach ($explode as $key => $value) { - while (strpos($value, 'YAMLString') !== false) { - $explode[$key] = preg_replace('/YAMLString/', $saved_strings[$i], $value, 1); - ++$i; - $value = $explode[$key]; - } - } - } - - return $explode; - } - - /** - * Builds the PHP array from all the YAML nodes we've gathered - * - * @return array - */ - protected function _buildArray() - { - $trunk = array(); - if (!isset($this->_indentSort[0])) { - return $trunk; - } - - foreach ($this->_indentSort[0] as $n) { - if (empty($n->parent)) { - $this->_nodeArrayizeData($n); - - // Check for references and copy the needed data to complete them. - $this->_makeReferences($n); - - // Merge our data with the big array we're building - $trunk = $this->_array_kmerge($trunk, $n->data); - } - } - - return $trunk; - } - - /** - * Traverses node-space and sets references (& and *) accordingly - * - * @return bool - */ - protected function _linkReferences() - { - if (is_array($this->_haveRefs)) { - foreach ($this->_haveRefs as $node) { - if (!empty($node->data)) { - $key = key($node->data); - // If it's an array, don't check. - if (is_array($node->data[$key])) { - foreach ($node->data[$key] as $k => $v) { - $this->_linkRef($node, $key, $k, $v); - } - } else { - $this->_linkRef($node, $key); - } - } - } - } - - return true; - } - - /** - * Helper for _linkReferences() - * - * @param Horde_Yaml_Node $n Node - * @param string $k Key - * @param mixed $v Value - * @return void - */ - function _linkRef(&$n, $key, $k = null, $v = null) - { - if (empty($k) && empty($v)) { - // Look for &refs - if (preg_match('/^&([^ ]+)/', $n->data[$key], $matches)) { - // Flag the node so we know it's a reference - $this->_allNodes[$n->id]->ref = substr($matches[0], 1); - $this->_allNodes[$n->id]->data[$key] = - substr($n->data[$key], strlen($matches[0]) + 1); - // Look for *refs - } elseif (preg_match('/^\*([^ ]+)/', $n->data[$key], $matches)) { - $ref = substr($matches[0], 1); - // Flag the node as having a reference - $this->_allNodes[$n->id]->refKey = $ref; - } - } elseif (!empty($k) && !empty($v)) { - if (preg_match('/^&([^ ]+)/', $v, $matches)) { - // Flag the node so we know it's a reference - $this->_allNodes[$n->id]->ref = substr($matches[0], 1); - $this->_allNodes[$n->id]->data[$key][$k] = - substr($v, strlen($matches[0]) + 1); - // Look for *refs - } elseif (preg_match('/^\*([^ ]+)/', $v, $matches)) { - $ref = substr($matches[0], 1); - // Flag the node as having a reference - $this->_allNodes[$n->id]->refKey = $ref; - } - } - } - - /** - * Finds the children of a node and aids in the building of the PHP array - * - * @param int $nid The id of the node whose children we're gathering - * @return array - */ - protected function _gatherChildren($nid) - { - $return = array(); - $node =& $this->_allNodes[$nid]; - if (is_array ($this->_allParent[$node->id])) { - foreach ($this->_allParent[$node->id] as $nodeZ) { - $z =& $this->_allNodes[$nodeZ]; - // We found a child - $this->_nodeArrayizeData($z); - - // Check for references - $this->_makeReferences($z); - - // Merge with the big array we're returning, the big - // array being all the data of the children of our - // parent node - $return = $this->_array_kmerge($return, $z->data); - } - } - return $return; - } - - /** - * Turns a node's data and its children's data into a PHP array - * - * @param array $node The node which you want to arrayize - * @return boolean - */ - protected function _nodeArrayizeData(&$node) - { - if ($node->children == true) { - if (is_array($node->data)) { - // This node has children, so we need to find them - $children = $this->_gatherChildren($node->id); - - // We've gathered all our children's data and are ready to use it - $key = key($node->data); - $key = empty($key) ? 0 : $key; - // If it's an array, add to it of course - if (isset($node->data[$key])) { - if (is_array($node->data[$key])) { - $node->data[$key] = $this->_array_kmerge($node->data[$key], $children); - } else { - $node->data[$key] = $children; - } - } else { - $node->data[$key] = $children; - } - } else { - // Same as above, find the children of this node - $children = $this->_gatherChildren($node->id); - $node->data = array(); - $node->data[] = $children; - } - } else { - // The node is a single string. See if we need to unserialize it. - if (is_array($node->data)) { - $key = key($node->data); - $key = empty($key) ? 0 : $key; - - if (!isset($node->data[$key]) || is_array($node->data[$key]) || is_object($node->data[$key])) { - return true; - } - - self::_unserialize($node->data[$key]); - } elseif (is_string($node->data)) { - self::_unserialize($node->data); - } - } - - // We edited $node by reference, so just return true - return true; - } - - /** - * Traverses node-space and copies references to / from this object. - * - * @param Horde_Yaml_Node $z A node whose references we wish to make real - * @return bool - */ - protected function _makeReferences(&$z) - { - // It is a reference - if (isset($z->ref)) { - $key = key($z->data); - // Copy the data to this object for easy retrieval later - $this->ref[$z->ref] =& $z->data[$key]; - // It has a reference - } elseif (isset($z->refKey)) { - if (isset($this->ref[$z->refKey])) { - $key = key($z->data); - // Copy the data from this object to make the node a real reference - $z->data[$key] =& $this->ref[$z->refKey]; - } - } - - return true; - } - - /** - * Merges two arrays, maintaining numeric keys. If two numeric - * keys clash, the second one will be appended to the resulting - * array. If string keys clash, the last one wins. - * - * @param array $arr1 - * @param array $arr2 - * @return array - */ - protected function _array_kmerge($arr1, $arr2) - { - while (list($key, $val) = each($arr2)) { - if (isset($arr1[$key]) && is_int($key)) { - $arr1[] = $val; - } else { - $arr1[$key] = $val; - } - } - - return $arr1; - } - -} diff --git a/News/includes/lib/YAML/Node.php b/News/includes/lib/YAML/Node.php deleted file mode 100644 index f6d8085..0000000 --- a/News/includes/lib/YAML/Node.php +++ /dev/null @@ -1,58 +0,0 @@ -id = $nodeId; - } - -} diff --git a/News/includes/lib/gettext/gettext.php b/News/includes/lib/gettext/gettext.php deleted file mode 100755 index 5064047..0000000 --- a/News/includes/lib/gettext/gettext.php +++ /dev/null @@ -1,432 +0,0 @@ -. - Copyright (c) 2005 Nico Kaiser - - This file is part of PHP-gettext. - - PHP-gettext 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. - - PHP-gettext 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 PHP-gettext; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -/** - * Provides a simple gettext replacement that works independently from - * the system's gettext abilities. - * It can read MO files and use them for translating strings. - * The files are passed to gettext_reader as a Stream (see streams.php) - * - * This version has the ability to cache all strings and translations to - * speed up the string lookup. - * While the cache is enabled by default, it can be switched off with the - * second parameter in the constructor (e.g. whenusing very large MO files - * that you don't want to keep in memory) - */ -class gettext_reader { - //public: - var $error = 0; // public variable that holds error code (0 if no error) - - //private: - var $BYTEORDER = 0; // 0: low endian, 1: big endian - var $STREAM = NULL; - var $short_circuit = false; - var $enable_cache = false; - var $originals = NULL; // offset of original table - var $translations = NULL; // offset of translation table - var $pluralheader = NULL; // cache header field for plural forms - var $total = 0; // total string count - var $table_originals = NULL; // table for original strings (offsets) - var $table_translations = NULL; // table for translated strings (offsets) - var $cache_translations = NULL; // original -> translation mapping - - - /* Methods */ - - - /** - * Reads a 32bit Integer from the Stream - * - * @access private - * @return Integer from the Stream - */ - function readint() { - if ($this->BYTEORDER == 0) { - // low endian - $input=unpack('V', $this->STREAM->read(4)); - return array_shift($input); - } else { - // big endian - $input=unpack('N', $this->STREAM->read(4)); - return array_shift($input); - } - } - - function read($bytes) { - return $this->STREAM->read($bytes); - } - - /** - * Reads an array of Integers from the Stream - * - * @param int count How many elements should be read - * @return Array of Integers - */ - function readintarray($count) { - if ($this->BYTEORDER == 0) { - // low endian - return unpack('V'.$count, $this->STREAM->read(4 * $count)); - } else { - // big endian - return unpack('N'.$count, $this->STREAM->read(4 * $count)); - } - } - - /** - * Constructor - * - * @param object Reader the StreamReader object - * @param boolean enable_cache Enable or disable caching of strings (default on) - */ - function gettext_reader($Reader, $enable_cache = true) { - // If there isn't a StreamReader, turn on short circuit mode. - if (! $Reader || isset($Reader->error) ) { - $this->short_circuit = true; - return; - } - - // Caching can be turned off - $this->enable_cache = $enable_cache; - - $MAGIC1 = "\x95\x04\x12\xde"; - $MAGIC2 = "\xde\x12\x04\x95"; - - $this->STREAM = $Reader; - $magic = $this->read(4); - if ($magic == $MAGIC1) { - $this->BYTEORDER = 1; - } elseif ($magic == $MAGIC2) { - $this->BYTEORDER = 0; - } else { - $this->error = 1; // not MO file - return false; - } - - // FIXME: Do we care about revision? We should. - $revision = $this->readint(); - - $this->total = $this->readint(); - $this->originals = $this->readint(); - $this->translations = $this->readint(); - } - - /** - * Loads the translation tables from the MO file into the cache - * If caching is enabled, also loads all strings into a cache - * to speed up translation lookups - * - * @access private - */ - function load_tables() { - if (is_array($this->cache_translations) && - is_array($this->table_originals) && - is_array($this->table_translations)) - return; - - /* get original and translations tables */ - if (!is_array($this->table_originals)) { - $this->STREAM->seekto($this->originals); - $this->table_originals = $this->readintarray($this->total * 2); - } - if (!is_array($this->table_translations)) { - $this->STREAM->seekto($this->translations); - $this->table_translations = $this->readintarray($this->total * 2); - } - - if ($this->enable_cache) { - $this->cache_translations = array (); - /* read all strings in the cache */ - for ($i = 0; $i < $this->total; $i++) { - $this->STREAM->seekto($this->table_originals[$i * 2 + 2]); - $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]); - $this->STREAM->seekto($this->table_translations[$i * 2 + 2]); - $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]); - $this->cache_translations[$original] = $translation; - } - } - } - - /** - * Returns a string from the "originals" table - * - * @access private - * @param int num Offset number of original string - * @return string Requested string if found, otherwise '' - */ - function get_original_string($num) { - $length = $this->table_originals[$num * 2 + 1]; - $offset = $this->table_originals[$num * 2 + 2]; - if (! $length) - return ''; - $this->STREAM->seekto($offset); - $data = $this->STREAM->read($length); - return (string)$data; - } - - /** - * Returns a string from the "translations" table - * - * @access private - * @param int num Offset number of original string - * @return string Requested string if found, otherwise '' - */ - function get_translation_string($num) { - $length = $this->table_translations[$num * 2 + 1]; - $offset = $this->table_translations[$num * 2 + 2]; - if (! $length) - return ''; - $this->STREAM->seekto($offset); - $data = $this->STREAM->read($length); - return (string)$data; - } - - /** - * Binary search for string - * - * @access private - * @param string string - * @param int start (internally used in recursive function) - * @param int end (internally used in recursive function) - * @return int string number (offset in originals table) - */ - function find_string($string, $start = -1, $end = -1) { - if (($start == -1) or ($end == -1)) { - // find_string is called with only one parameter, set start end end - $start = 0; - $end = $this->total; - } - if (abs($start - $end) <= 1) { - // We're done, now we either found the string, or it doesn't exist - $txt = $this->get_original_string($start); - if ($string == $txt) - return $start; - else - return -1; - } else if ($start > $end) { - // start > end -> turn around and start over - return $this->find_string($string, $end, $start); - } else { - // Divide table in two parts - $half = (int)(($start + $end) / 2); - $cmp = strcmp($string, $this->get_original_string($half)); - if ($cmp == 0) - // string is exactly in the middle => return it - return $half; - else if ($cmp < 0) - // The string is in the upper half - return $this->find_string($string, $start, $half); - else - // The string is in the lower half - return $this->find_string($string, $half, $end); - } - } - - /** - * Translates a string - * - * @access public - * @param string string to be translated - * @return string translated string (or original, if not found) - */ - function translate($string) { - if ($this->short_circuit) - return $string; - $this->load_tables(); - - if ($this->enable_cache) { - // Caching enabled, get translated string from cache - if (array_key_exists($string, $this->cache_translations)) - return $this->cache_translations[$string]; - else - return $string; - } else { - // Caching not enabled, try to find string - $num = $this->find_string($string); - if ($num == -1) - return $string; - else - return $this->get_translation_string($num); - } - } - - /** - * Sanitize plural form expression for use in PHP eval call. - * - * @access private - * @return string sanitized plural form expression - */ - function sanitize_plural_expression($expr) { - // Get rid of disallowed characters. - $expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr); - - // Add parenthesis for tertiary '?' operator. - $expr .= ';'; - $res = ''; - $p = 0; - for ($i = 0; $i < strlen($expr); $i++) { - $ch = $expr[$i]; - switch ($ch) { - case '?': - $res .= ' ? ('; - $p++; - break; - case ':': - $res .= ') : ('; - break; - case ';': - $res .= str_repeat( ')', $p) . ';'; - $p = 0; - break; - default: - $res .= $ch; - } - } - return $res; - } - - /** - * Parse full PO header and extract only plural forms line. - * - * @access private - * @return string verbatim plural form header field - */ - function extract_plural_forms_header_from_po_header($header) { - if (preg_match("/(^|\n)plural-forms: ([^\n]*)\n/i", $header, $regs)) - $expr = $regs[2]; - else - $expr = "nplurals=2; plural=n == 1 ? 0 : 1;"; - return $expr; - } - - /** - * Get possible plural forms from MO header - * - * @access private - * @return string plural form header - */ - function get_plural_forms() { - // lets assume message number 0 is header - // this is true, right? - $this->load_tables(); - - // cache header field for plural forms - if (! is_string($this->pluralheader)) { - if ($this->enable_cache) { - $header = $this->cache_translations[""]; - } else { - $header = $this->get_translation_string(0); - } - $expr = $this->extract_plural_forms_header_from_po_header($header); - $this->pluralheader = $this->sanitize_plural_expression($expr); - } - return $this->pluralheader; - } - - /** - * Detects which plural form to take - * - * @access private - * @param n count - * @return int array index of the right plural form - */ - function select_string($n) { - $string = $this->get_plural_forms(); - $string = str_replace('nplurals',"\$total",$string); - $string = str_replace("n",$n,$string); - $string = str_replace('plural',"\$plural",$string); - - $total = 0; - $plural = 0; - - eval("$string"); - if ($plural >= $total) $plural = $total - 1; - return $plural; - } - - /** - * Plural version of gettext - * - * @access public - * @param string single - * @param string plural - * @param string number - * @return translated plural form - */ - function ngettext($single, $plural, $number) { - if ($this->short_circuit) { - if ($number != 1) - return $plural; - else - return $single; - } - - // find out the appropriate form - $select = $this->select_string($number); - - // this should contains all strings separated by NULLs - $key = $single . chr(0) . $plural; - - - if ($this->enable_cache) { - if (! array_key_exists($key, $this->cache_translations)) { - return ($number != 1) ? $plural : $single; - } else { - $result = $this->cache_translations[$key]; - $list = explode(chr(0), $result); - return $list[$select]; - } - } else { - $num = $this->find_string($key); - if ($num == -1) { - return ($number != 1) ? $plural : $single; - } else { - $result = $this->get_translation_string($num); - $list = explode(chr(0), $result); - return $list[$select]; - } - } - } - - function pgettext($context, $msgid) { - $key = $context . chr(4) . $msgid; - $ret = $this->translate($key); - if (strpos($ret, "\004") !== FALSE) { - return $msgid; - } else { - return $ret; - } - } - - function npgettext($context, $singular, $plural, $number) { - $key = $context . chr(4) . $singular; - $ret = $this->ngettext($key, $plural, $number); - if (strpos($ret, "\004") !== FALSE) { - return $singular; - } else { - return $ret; - } - - } -} - -?> diff --git a/News/includes/lib/gettext/streams.php b/News/includes/lib/gettext/streams.php deleted file mode 100755 index 3cdc158..0000000 --- a/News/includes/lib/gettext/streams.php +++ /dev/null @@ -1,167 +0,0 @@ -. - - This file is part of PHP-gettext. - - PHP-gettext 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. - - PHP-gettext 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 PHP-gettext; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - - - // Simple class to wrap file streams, string streams, etc. - // seek is essential, and it should be byte stream -class StreamReader { - // should return a string [FIXME: perhaps return array of bytes?] - function read($bytes) { - return false; - } - - // should return new position - function seekto($position) { - return false; - } - - // returns current position - function currentpos() { - return false; - } - - // returns length of entire stream (limit for seekto()s) - function length() { - return false; - } -}; - -class StringReader { - var $_pos; - var $_str; - - function StringReader($str='') { - $this->_str = $str; - $this->_pos = 0; - } - - function read($bytes) { - $data = substr($this->_str, $this->_pos, $bytes); - $this->_pos += $bytes; - if (strlen($this->_str)<$this->_pos) - $this->_pos = strlen($this->_str); - - return $data; - } - - function seekto($pos) { - $this->_pos = $pos; - if (strlen($this->_str)<$this->_pos) - $this->_pos = strlen($this->_str); - return $this->_pos; - } - - function currentpos() { - return $this->_pos; - } - - function length() { - return strlen($this->_str); - } - -}; - - -class FileReader { - var $_pos; - var $_fd; - var $_length; - - function FileReader($filename) { - if (file_exists($filename)) { - - $this->_length=filesize($filename); - $this->_pos = 0; - $this->_fd = fopen($filename,'rb'); - if (!$this->_fd) { - $this->error = 3; // Cannot read file, probably permissions - return false; - } - } else { - $this->error = 2; // File doesn't exist - return false; - } - } - - function read($bytes) { - if ($bytes) { - fseek($this->_fd, $this->_pos); - - // PHP 5.1.1 does not read more than 8192 bytes in one fread() - // the discussions at PHP Bugs suggest it's the intended behaviour - $data = ''; - while ($bytes > 0) { - $chunk = fread($this->_fd, $bytes); - $data .= $chunk; - $bytes -= strlen($chunk); - } - $this->_pos = ftell($this->_fd); - - return $data; - } else return ''; - } - - function seekto($pos) { - fseek($this->_fd, $pos); - $this->_pos = ftell($this->_fd); - return $this->_pos; - } - - function currentpos() { - return $this->_pos; - } - - function length() { - return $this->_length; - } - - function close() { - fclose($this->_fd); - } - -}; - -// Preloads entire file in memory first, then creates a StringReader -// over it (it assumes knowledge of StringReader internals) -class CachedFileReader extends StringReader { - function CachedFileReader($filename) { - if (file_exists($filename)) { - - $length=filesize($filename); - $fd = fopen($filename,'rb'); - - if (!$fd) { - $this->error = 3; // Cannot read file, probably permissions - return false; - } - $this->_str = fread($fd, $length); - fclose($fd); - - } else { - $this->error = 2; // File doesn't exist - return false; - } - } -}; - - -?> diff --git a/News/includes/lib/gz.php b/News/includes/lib/gz.php deleted file mode 100755 index 111cf68..0000000 --- a/News/includes/lib/gz.php +++ /dev/null @@ -1,39 +0,0 @@ - 0 ) - exit("GTFO."); - - if (extension_loaded('zlib') and USE_ZLIB and ini_get('zlib.output_compression') === 'On') { - @ini_set('zlib.output_compression', 'Off'); - ob_start("ob_gzhandler"); - header("Content-Encoding: gzip"); - } else - ob_start(); - - header("Content-Type: application/x-javascript"); - - if (strpos($_GET['file'], "/themes/") === 0) { - # Constant: MAIN_DIR - # Absolute path to the Chyrp root - define('MAIN_DIR', dirname(dirname(dirname(__FILE__)))); - - header("Last-Modified: ".@date("r", filemtime(MAIN_DIR.$_GET['file']))); - - if (file_exists(MAIN_DIR.$_GET['file'])) - readfile(MAIN_DIR.$_GET['file']); - else - echo "alert('File not found: ".addslashes($_GET['file'])."')"; - } elseif (file_exists($_GET['file'])) { - header("Last-Modified: ".@date("r", filemtime($_GET['file']))); - readfile($_GET['file']); - } else - echo "alert('File not found: ".addslashes($_GET['file'])."')"; - - ob_end_flush(); diff --git a/News/includes/lib/ixr.php b/News/includes/lib/ixr.php deleted file mode 100755 index 8dc1608..0000000 --- a/News/includes/lib/ixr.php +++ /dev/null @@ -1,1343 +0,0 @@ -data = $data; - if (!$type) { - $type = $this->calculateType(); - } - $this->type = $type; - if ($type == 'struct') { - // Turn all the values in the array in to new IXR_Value objects - foreach ($this->data as $key => $value) { - $this->data[$key] = new IXR_Value($value); - } - } - if ($type == 'array') { - for ($i = 0, $j = count($this->data); $i < $j; $i++) { - $this->data[$i] = new IXR_Value($this->data[$i]); - } - } - } - - function calculateType() - { - if ($this->data === true || $this->data === false) { - return 'boolean'; - } - if (is_integer($this->data)) { - return 'int'; - } - if (is_double($this->data)) { - return 'double'; - } - - // Deal with IXR object types base64 and date - if (is_object($this->data) && is_a($this->data, 'IXR_Date')) { - return 'date'; - } - if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) { - return 'base64'; - } - - // If it is a normal PHP object convert it in to a struct - if (is_object($this->data)) { - $this->data = get_object_vars($this->data); - return 'struct'; - } - if (!is_array($this->data)) { - return 'string'; - } - - // We have an array - is it an array or a struct? - if ($this->isStruct($this->data)) { - return 'struct'; - } else { - return 'array'; - } - } - - function getXml() - { - // Return XML for this value - switch ($this->type) { - case 'boolean': - return ''.(($this->data) ? '1' : '0').''; - break; - case 'int': - return ''.$this->data.''; - break; - case 'double': - return ''.$this->data.''; - break; - case 'string': - return ''.htmlspecialchars($this->data).''; - break; - case 'array': - $return = ''."\n"; - foreach ($this->data as $item) { - $return .= ' '.$item->getXml()."\n"; - } - $return .= ''; - return $return; - break; - case 'struct': - $return = ''."\n"; - foreach ($this->data as $name => $value) { - $return .= " $name"; - $return .= $value->getXml()."\n"; - } - $return .= ''; - return $return; - break; - case 'date': - case 'base64': - return $this->data->getXml(); - break; - } - return false; - } - - /** - * Checks whether or not the supplied array is a struct or not - * - * @param unknown_type $array - * @return boolean - */ - function isStruct($array) - { - $expected = 0; - foreach ($array as $key => $value) { - if ((string)$key != (string)$expected) { - return true; - } - $expected++; - } - return false; - } -} - -/** - * IXR_MESSAGE - * - * @package IXR - * @since 1.5 - * - */ -class IXR_Message -{ - var $message; - var $messageType; // methodCall / methodResponse / fault - var $faultCode; - var $faultString; - var $methodName; - var $params; - - // Current variable stacks - var $_arraystructs = array(); // The stack used to keep track of the current array/struct - var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array - var $_currentStructName = array(); // A stack as well - var $_param; - var $_value; - var $_currentTag; - var $_currentTagContents; - // The XML parser - var $_parser; - - function IXR_Message($message) - { - $this->message =& $message; - } - - function parse() - { - // first remove the XML declaration - // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages - $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr($this->message, 0, 100), 1); - $this->message = substr_replace($this->message, $header, 0, 100); - if (trim($this->message) == '') { - return false; - } - $this->_parser = xml_parser_create(); - // Set XML parser to take the case of tags in to account - xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); - // Set XML parser callback functions - xml_set_object($this->_parser, $this); - xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); - xml_set_character_data_handler($this->_parser, 'cdata'); - $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages - do { - if (strlen($this->message) <= $chunk_size) { - $final = true; - } - $part = substr($this->message, 0, $chunk_size); - $this->message = substr($this->message, $chunk_size); - if (!xml_parse($this->_parser, $part, $final)) { - return false; - } - if ($final) { - break; - } - } while (true); - xml_parser_free($this->_parser); - - // Grab the error messages, if any - if ($this->messageType == 'fault') { - $this->faultCode = $this->params[0]['faultCode']; - $this->faultString = $this->params[0]['faultString']; - } - return true; - } - - function tag_open($parser, $tag, $attr) - { - $this->_currentTagContents = ''; - $this->currentTag = $tag; - switch($tag) { - case 'methodCall': - case 'methodResponse': - case 'fault': - $this->messageType = $tag; - break; - /* Deal with stacks of arrays and structs */ - case 'data': // data is to all intents and puposes more interesting than array - $this->_arraystructstypes[] = 'array'; - $this->_arraystructs[] = array(); - break; - case 'struct': - $this->_arraystructstypes[] = 'struct'; - $this->_arraystructs[] = array(); - break; - } - } - - function cdata($parser, $cdata) - { - $this->_currentTagContents .= $cdata; - } - - function tag_close($parser, $tag) - { - $valueFlag = false; - switch($tag) { - case 'int': - case 'i4': - $value = (int)trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'double': - $value = (double)trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'string': - $value = (string)trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'dateTime.iso8601': - $value = new IXR_Date(trim($this->_currentTagContents)); - $valueFlag = true; - break; - case 'value': - // "If no type is indicated, the type is string." - if (trim($this->_currentTagContents) != '') { - $value = (string)$this->_currentTagContents; - $valueFlag = true; - } - break; - case 'boolean': - $value = (boolean)trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'base64': - $value = base64_decode($this->_currentTagContents); - $valueFlag = true; - break; - /* Deal with stacks of arrays and structs */ - case 'data': - case 'struct': - $value = array_pop($this->_arraystructs); - array_pop($this->_arraystructstypes); - $valueFlag = true; - break; - case 'member': - array_pop($this->_currentStructName); - break; - case 'name': - $this->_currentStructName[] = trim($this->_currentTagContents); - break; - case 'methodName': - $this->methodName = trim($this->_currentTagContents); - break; - } - - if ($valueFlag) { - if (count($this->_arraystructs) > 0) { - // Add value to struct or array - if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { - // Add to struct - $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; - } else { - // Add to array - $this->_arraystructs[count($this->_arraystructs)-1][] = $value; - } - } else { - // Just add as a paramater - $this->params[] = $value; - } - } - $this->_currentTagContents = ''; - } -} - -/** - * IXR_Server - * - * @package IXR - * @since 1.5 - */ -class IXR_Server -{ - var $data; - var $callbacks = array(); - var $message; - var $capabilities; - - function IXR_Server($callbacks = false, $data = false, $wait = false) - { - $this->setCapabilities(); - if ($callbacks) { - $this->callbacks = $callbacks; - } - $this->setCallbacks(); - if (!$wait) { - $this->serve($data); - } - } - - function serve($data = false) - { - if (!$data) { - if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') { - header('Content-Type: text/plain'); // merged from WP #9093 - die('XML-RPC server accepts POST requests only.'); - } - - global $HTTP_RAW_POST_DATA; - if (empty($HTTP_RAW_POST_DATA)) { - // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293 - $data = file_get_contents('php://input'); - } else { - $data =& $HTTP_RAW_POST_DATA; - } - } - $this->message = new IXR_Message($data); - if (!$this->message->parse()) { - $this->error(-32700, 'parse error. not well formed'); - } - if ($this->message->messageType != 'methodCall') { - $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); - } - $result = $this->call($this->message->methodName, $this->message->params); - - // Is the result an error? - if (is_a($result, 'IXR_Error')) { - $this->error($result); - } - - // Encode the result - $r = new IXR_Value($result); - $resultxml = $r->getXml(); - - // Create the XML - $xml = << - - - - $resultxml - - - - - -EOD; - // Send it - $this->output($xml); - } - - function call($methodname, $args) - { - if (!$this->hasMethod($methodname)) { - return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); - } - $method = $this->callbacks[$methodname]; - - // Perform the callback and send the response - if (count($args) == 1) { - // If only one paramater just send that instead of the whole array - $args = $args[0]; - } - - // Are we dealing with a function or a method? - if (is_string($method) && substr($method, 0, 5) == 'this:') { - // It's a class method - check it exists - $method = substr($method, 5); - if (!method_exists($this, $method)) { - return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); - } - - //Call the method - $result = $this->$method($args); - } else { - // It's a function - does it exist? - if (is_array($method)) { - if (!method_exists($method[0], $method[1])) { - return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.'); - } - } else if (!function_exists($method)) { - return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); - } - - // Call the function - $result = call_user_func($method, $args); - } - return $result; - } - - function error($error, $message = false) - { - // Accepts either an error object or an error code and message - if ($message && !is_object($error)) { - $error = new IXR_Error($error, $message); - } - $this->output($error->getXml()); - } - - function output($xml) - { - $xml = ''."\n".$xml; - $length = strlen($xml); - header('Connection: close'); - header('Content-Length: '.$length); - header('Content-Type: text/xml'); - header('Date: '.date('r')); - echo $xml; - exit; - } - - function hasMethod($method) - { - return in_array($method, array_keys($this->callbacks)); - } - - function setCapabilities() - { - // Initialises capabilities array - $this->capabilities = array( - 'xmlrpc' => array( - 'specUrl' => 'http://www.xmlrpc.com/spec', - 'specVersion' => 1 - ), - 'faults_interop' => array( - 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', - 'specVersion' => 20010516 - ), - 'system.multicall' => array( - 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', - 'specVersion' => 1 - ), - ); - } - - function getCapabilities($args) - { - return $this->capabilities; - } - - function setCallbacks() - { - $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; - $this->callbacks['system.listMethods'] = 'this:listMethods'; - $this->callbacks['system.multicall'] = 'this:multiCall'; - } - - function listMethods($args) - { - // Returns a list of methods - uses array_reverse to ensure user defined - // methods are listed before server defined methods - return array_reverse(array_keys($this->callbacks)); - } - - function multiCall($methodcalls) - { - // See http://www.xmlrpc.com/discuss/msgReader$1208 - $return = array(); - foreach ($methodcalls as $call) { - $method = $call['methodName']; - $params = $call['params']; - if ($method == 'system.multicall') { - $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); - } else { - $result = $this->call($method, $params); - } - if (is_a($result, 'IXR_Error')) { - $return[] = array( - 'faultCode' => $result->code, - 'faultString' => $result->message - ); - } else { - $return[] = array($result); - } - } - return $return; - } -} - -/** - * IXR_Request - * - * @package IXR - * @since 1.5 - */ -class IXR_Request -{ - var $method; - var $args; - var $xml; - - function IXR_Request($method, $args) - { - $this->method = $method; - $this->args = $args; - $this->xml = << - -{$this->method} - - -EOD; - foreach ($this->args as $arg) { - $this->xml .= ''; - $v = new IXR_Value($arg); - $this->xml .= $v->getXml(); - $this->xml .= "\n"; - } - $this->xml .= ''; - } - - function getLength() - { - return strlen($this->xml); - } - - function getXml() - { - return $this->xml; - } -} - -/** - * IXR_Client - * - * @package IXR - * @since 1.5 - * - */ -class IXR_Client -{ - var $server; - var $port; - var $path; - var $useragent; - var $response; - var $message = false; - var $debug = false; - var $timeout; - - // Storage place for an error message - var $error = false; - - function IXR_Client($server, $path = false, $port = 80, $timeout = 15) - { - if (!$path) { - // Assume we have been given a URL instead - $bits = parse_url($server); - $this->server = $bits['host']; - $this->port = isset($bits['port']) ? $bits['port'] : 80; - $this->path = isset($bits['path']) ? $bits['path'] : '/'; - - // Make absolutely sure we have a path - if (!$this->path) { - $this->path = '/'; - } - } else { - $this->server = $server; - $this->path = $path; - $this->port = $port; - } - $this->useragent = 'The Incutio XML-RPC PHP Library'; - $this->timeout = $timeout; - } - - function query() - { - $args = func_get_args(); - $method = array_shift($args); - $request = new IXR_Request($method, $args); - $length = $request->getLength(); - $xml = $request->getXml(); - $r = "\r\n"; - $request = "POST {$this->path} HTTP/1.0$r"; - - // Merged from WP #8145 - allow custom headers - $this->headers['Host'] = $this->server; - $this->headers['Content-Type'] = 'text/xml'; - $this->headers['User-Agent'] = $this->useragent; - $this->headers['Content-Length']= $length; - - foreach( $this->headers as $header => $value ) { - $request .= "{$header}: {$value}{$r}"; - } - $request .= $r; - - $request .= $xml; - - // Now send the request - if ($this->debug) { - echo '
'.htmlspecialchars($request)."\n
\n\n"; - } - - if ($this->timeout) { - $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); - } else { - $fp = @fsockopen($this->server, $this->port, $errno, $errstr); - } - if (!$fp) { - $this->error = new IXR_Error(-32300, 'transport error - could not open socket'); - return false; - } - fputs($fp, $request); - $contents = ''; - $debugContents = ''; - $gotFirstLine = false; - $gettingHeaders = true; - while (!feof($fp)) { - $line = fgets($fp, 4096); - if (!$gotFirstLine) { - // Check line for '200' - if (strstr($line, '200') === false) { - $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200'); - return false; - } - $gotFirstLine = true; - } - if (trim($line) == '') { - $gettingHeaders = false; - } - if (!$gettingHeaders) { - // merged from WP #12559 - remove trim - $contents .= $line; - } - if ($this->debug) { - $debugContents .= $line; - } - } - if ($this->debug) { - echo '
'.htmlspecialchars($debugContents)."\n
\n\n"; - } - - // Now parse what we've got back - $this->message = new IXR_Message($contents); - if (!$this->message->parse()) { - // XML error - $this->error = new IXR_Error(-32700, 'parse error. not well formed'); - return false; - } - - // Is the message a fault? - if ($this->message->messageType == 'fault') { - $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); - return false; - } - - // Message must be OK - return true; - } - - function getResponse() - { - // methodResponses can only have one param - return that - return $this->message->params[0]; - } - - function isError() - { - return (is_object($this->error)); - } - - function getErrorCode() - { - return $this->error->code; - } - - function getErrorMessage() - { - return $this->error->message; - } -} - - -/** - * IXR_Error - * - * @package IXR - * @since 1.5 - */ -class IXR_Error -{ - var $code; - var $message; - - function IXR_Error($code, $message) - { - $this->code = $code; - $this->message = htmlspecialchars($message); - } - - function getXml() - { - $xml = << - - - - - faultCode - {$this->code} - - - faultString - {$this->message} - - - - - - -EOD; - return $xml; - } -} - -/** - * IXR_Date - * - * @package IXR - * @since 1.5 - */ -class IXR_Date { - var $year; - var $month; - var $day; - var $hour; - var $minute; - var $second; - var $timezone; - - function IXR_Date($time) - { - // $time can be a PHP timestamp or an ISO one - if (is_numeric($time)) { - $this->parseTimestamp($time); - } else { - $this->parseIso($time); - } - } - - function parseTimestamp($timestamp) - { - $this->year = date('Y', $timestamp); - $this->month = date('m', $timestamp); - $this->day = date('d', $timestamp); - $this->hour = date('H', $timestamp); - $this->minute = date('i', $timestamp); - $this->second = date('s', $timestamp); - $this->timezone = ''; - } - - function parseIso($iso) - { - $this->year = substr($iso, 0, 4); - $this->month = substr($iso, 4, 2); - $this->day = substr($iso, 6, 2); - $this->hour = substr($iso, 9, 2); - $this->minute = substr($iso, 12, 2); - $this->second = substr($iso, 15, 2); - $this->timezone = substr($iso, 17); - } - - function getIso() - { - return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone; - } - - function getXml() - { - return ''.$this->getIso().''; - } - - function getTimestamp() - { - return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); - } -} - -/** - * IXR_Base64 - * - * @package IXR - * @since 1.5 - */ -class IXR_Base64 -{ - var $data; - - function IXR_Base64($data) - { - $this->data = $data; - } - - function getXml() - { - return ''.base64_encode($this->data).''; - } -} - -/** - * IXR_IntrospectionServer - * - * @package IXR - * @since 1.5 - */ -class IXR_IntrospectionServer extends IXR_Server -{ - var $signatures; - var $help; - - function IXR_IntrospectionServer() - { - $this->setCallbacks(); - $this->setCapabilities(); - $this->capabilities['introspection'] = array( - 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', - 'specVersion' => 1 - ); - $this->addCallback( - 'system.methodSignature', - 'this:methodSignature', - array('array', 'string'), - 'Returns an array describing the return type and required parameters of a method' - ); - $this->addCallback( - 'system.getCapabilities', - 'this:getCapabilities', - array('struct'), - 'Returns a struct describing the XML-RPC specifications supported by this server' - ); - $this->addCallback( - 'system.listMethods', - 'this:listMethods', - array('array'), - 'Returns an array of available methods on this server' - ); - $this->addCallback( - 'system.methodHelp', - 'this:methodHelp', - array('string', 'string'), - 'Returns a documentation string for the specified method' - ); - } - - function addCallback($method, $callback, $args, $help) - { - $this->callbacks[$method] = $callback; - $this->signatures[$method] = $args; - $this->help[$method] = $help; - } - - function call($methodname, $args) - { - // Make sure it's in an array - if ($args && !is_array($args)) { - $args = array($args); - } - - // Over-rides default call method, adds signature check - if (!$this->hasMethod($methodname)) { - return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.'); - } - $method = $this->callbacks[$methodname]; - $signature = $this->signatures[$methodname]; - $returnType = array_shift($signature); - - // Check the number of arguments - if (count($args) != count($signature)) { - return new IXR_Error(-32602, 'server error. wrong number of method parameters'); - } - - // Check the argument types - $ok = true; - $argsbackup = $args; - for ($i = 0, $j = count($args); $i < $j; $i++) { - $arg = array_shift($args); - $type = array_shift($signature); - switch ($type) { - case 'int': - case 'i4': - if (is_array($arg) || !is_int($arg)) { - $ok = false; - } - break; - case 'base64': - case 'string': - if (!is_string($arg)) { - $ok = false; - } - break; - case 'boolean': - if ($arg !== false && $arg !== true) { - $ok = false; - } - break; - case 'float': - case 'double': - if (!is_float($arg)) { - $ok = false; - } - break; - case 'date': - case 'dateTime.iso8601': - if (!is_a($arg, 'IXR_Date')) { - $ok = false; - } - break; - } - if (!$ok) { - return new IXR_Error(-32602, 'server error. invalid method parameters'); - } - } - // It passed the test - run the "real" method call - return parent::call($methodname, $argsbackup); - } - - function methodSignature($method) - { - if (!$this->hasMethod($method)) { - return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.'); - } - // We should be returning an array of types - $types = $this->signatures[$method]; - $return = array(); - foreach ($types as $type) { - switch ($type) { - case 'string': - $return[] = 'string'; - break; - case 'int': - case 'i4': - $return[] = 42; - break; - case 'double': - $return[] = 3.1415; - break; - case 'dateTime.iso8601': - $return[] = new IXR_Date(time()); - break; - case 'boolean': - $return[] = true; - break; - case 'base64': - $return[] = new IXR_Base64('base64'); - break; - case 'array': - $return[] = array('array'); - break; - case 'struct': - $return[] = array('struct' => 'struct'); - break; - } - } - return $return; - } - - function methodHelp($method) - { - return $this->help[$method]; - } -} - -/** - * IXR_ClientMulticall - * - * @package IXR - * @since 1.5 - */ -class IXR_ClientMulticall extends IXR_Client -{ - var $calls = array(); - - function IXR_ClientMulticall($server, $path = false, $port = 80) - { - parent::IXR_Client($server, $path, $port); - $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; - } - - function addCall() - { - $args = func_get_args(); - $methodName = array_shift($args); - $struct = array( - 'methodName' => $methodName, - 'params' => $args - ); - $this->calls[] = $struct; - } - - function query() - { - // Prepare multicall, then call the parent::query() method - return parent::query('system.multicall', $this->calls); - } -} - -/** - * Client for communicating with a XML-RPC Server over HTTPS. - * - * @author Jason Stirk (@link http://blog.griffin.homelinux.org/projects/xmlrpc/) - * @version 0.2.0 26May2005 08:34 +0800 - * @copyright (c) 2004-2005 Jason Stirk - * @package IXR - */ -class IXR_ClientSSL extends IXR_Client -{ - /** - * Filename of the SSL Client Certificate - * @access private - * @since 0.1.0 - * @var string - */ - var $_certFile; - - /** - * Filename of the SSL CA Certificate - * @access private - * @since 0.1.0 - * @var string - */ - var $_caFile; - - /** - * Filename of the SSL Client Private Key - * @access private - * @since 0.1.0 - * @var string - */ - var $_keyFile; - - /** - * Passphrase to unlock the private key - * @access private - * @since 0.1.0 - * @var string - */ - var $_passphrase; - - /** - * Constructor - * @param string $server URL of the Server to connect to - * @since 0.1.0 - */ - function IXR_ClientSSL($server, $path = false, $port = 443, $timeout = false) - { - parent::IXR_Client($server, $path, $port, $timeout); - $this->useragent = 'The Incutio XML-RPC PHP Library for SSL'; - - // Set class fields - $this->_certFile=false; - $this->_caFile=false; - $this->_keyFile=false; - $this->_passphrase=''; - } - - /** - * Set the client side certificates to communicate with the server. - * - * @since 0.1.0 - * @param string $certificateFile Filename of the client side certificate to use - * @param string $keyFile Filename of the client side certificate's private key - * @param string $keyPhrase Passphrase to unlock the private key - */ - function setCertificate($certificateFile, $keyFile, $keyPhrase='') - { - // Check the files all exist - if (is_file($certificateFile)) { - $this->_certFile = $certificateFile; - } else { - die('Could not open certificate: ' . $certificateFile); - } - - if (is_file($keyFile)) { - $this->_keyFile = $keyFile; - } else { - die('Could not open private key: ' . $keyFile); - } - - $this->_passphrase=(string)$keyPhrase; - } - - function setCACertificate($caFile) - { - if (is_file($caFile)) { - $this->_caFile = $caFile; - } else { - die('Could not open CA certificate: ' . $caFile); - } - } - - /** - * Sets the connection timeout (in seconds) - * @param int $newTimeOut Timeout in seconds - * @returns void - * @since 0.1.2 - */ - function setTimeOut($newTimeOut) - { - $this->timeout = (int)$newTimeOut; - } - - /** - * Returns the connection timeout (in seconds) - * @returns int - * @since 0.1.2 - */ - function getTimeOut() - { - return $this->timeout; - } - - /** - * Set the query to send to the XML-RPC Server - * @since 0.1.0 - */ - function query() - { - $args = func_get_args(); - $method = array_shift($args); - $request = new IXR_Request($method, $args); - $length = $request->getLength(); - $xml = $request->getXml(); - - if ($this->debug) { - echo '
'.htmlspecialchars($xml)."\n
\n\n"; - } - - //This is where we deviate from the normal query() - //Rather than open a normal sock, we will actually use the cURL - //extensions to make the calls, and handle the SSL stuff. - - //Since 04Aug2004 (0.1.3) - Need to include the port (duh...) - //Since 06Oct2004 (0.1.4) - Need to include the colon!!! - // (I swear I've fixed this before... ESP in live... But anyhu...) - $curl=curl_init('https://' . $this->server . ':' . $this->port . $this->path); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - - //Since 23Jun2004 (0.1.2) - Made timeout a class field - curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout); - - if ($this->debug) { - curl_setopt($curl, CURLOPT_VERBOSE, 1); - } - - curl_setopt($curl, CURLOPT_HEADER, 1); - curl_setopt($curl, CURLOPT_POST, 1); - curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); - curl_setopt($curl, CURLOPT_PORT, $this->port); - curl_setopt($curl, CURLOPT_HTTPHEADER, array( - "Content-Type: text/xml", - "Content-length: {$length}")); - - // Process the SSL certificates, etc. to use - if (!($this->_certFile === false)) { - // We have a certificate file set, so add these to the cURL handler - curl_setopt($curl, CURLOPT_SSLCERT, $this->_certFile); - curl_setopt($curl, CURLOPT_SSLKEY, $this->_keyFile); - - if ($this->debug) { - echo "SSL Cert at : " . $this->_certFile . "\n"; - echo "SSL Key at : " . $this->_keyFile . "\n"; - } - - // See if we need to give a passphrase - if (!($this->_passphrase === '')) { - curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $this->_passphrase); - } - - if ($this->_caFile === false) { - // Don't verify their certificate, as we don't have a CA to verify against - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); - } else { - // Verify against a CA - curl_setopt($curl, CURLOPT_CAINFO, $this->_caFile); - } - } - - // Call cURL to do it's stuff and return us the content - $contents = curl_exec($curl); - curl_close($curl); - - // Check for 200 Code in $contents - if (!strstr($contents, '200 OK')) { - //There was no "200 OK" returned - we failed - $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200'); - return false; - } - - if ($this->debug) { - echo '
'.htmlspecialchars($contents)."\n
\n\n"; - } - // Now parse what we've got back - // Since 20Jun2004 (0.1.1) - We need to remove the headers first - // Why I have only just found this, I will never know... - // So, remove everything before the first < - $contents = substr($contents,strpos($contents, '<')); - - $this->message = new IXR_Message($contents); - if (!$this->message->parse()) { - // XML error - $this->error = new IXR_Error(-32700, 'parse error. not well formed'); - return false; - } - // Is the message a fault? - if ($this->message->messageType == 'fault') { - $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); - return false; - } - - // Message must be OK - return true; - } -} - -/** - * Extension of the {@link IXR_Server} class to easily wrap objects. - * - * Class is designed to extend the existing XML-RPC server to allow the - * presentation of methods from a variety of different objects via an - * XML-RPC server. - * It is intended to assist in organization of your XML-RPC methods by allowing - * you to "write once" in your existing model classes and present them. - * - * @author Jason Stirk - * @version 1.0.1 19Apr2005 17:40 +0800 - * @copyright Copyright (c) 2005 Jason Stirk - * @package IXR - */ -class IXR_ClassServer extends IXR_Server -{ - var $_objects; - var $_delim; - - function IXR_ClassServer($delim = '.', $wait = false) - { - $this->IXR_Server(array(), false, $wait); - $this->_delimiter = $delim; - $this->_objects = array(); - } - - function addMethod($rpcName, $functionName) - { - $this->callbacks[$rpcName] = $functionName; - } - - function registerObject($object, $methods, $prefix=null) - { - if (is_null($prefix)) - { - $prefix = get_class($object); - } - $this->_objects[$prefix] = $object; - - // Add to our callbacks array - foreach($methods as $method) - { - if (is_array($method)) - { - $targetMethod = $method[0]; - $method = $method[1]; - } - else - { - $targetMethod = $method; - } - $this->callbacks[$prefix . $this->_delimiter . $method]=array($prefix, $targetMethod); - } - } - - function call($methodname, $args) - { - if (!$this->hasMethod($methodname)) { - return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); - } - $method = $this->callbacks[$methodname]; - - // Perform the callback and send the response - if (count($args) == 1) { - // If only one paramater just send that instead of the whole array - $args = $args[0]; - } - - // See if this method comes from one of our objects or maybe self - if (is_array($method) || (substr($method, 0, 5) == 'this:')) { - if (is_array($method)) { - $object=$this->_objects[$method[0]]; - $method=$method[1]; - } else { - $object=$this; - $method = substr($method, 5); - } - - // It's a class method - check it exists - if (!method_exists($object, $method)) { - return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); - } - - // Call the method - $result = $object->$method($args); - } else { - // It's a function - does it exist? - if (!function_exists($method)) { - return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); - } - - // Call the function - $result = $method($args); - } - return $result; - } -} diff --git a/News/includes/lib/jquery.js b/News/includes/lib/jquery.js deleted file mode 100644 index 8f3ca2e..0000000 --- a/News/includes/lib/jquery.js +++ /dev/null @@ -1,167 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.4 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu Nov 11 19:04:53 2010 -0500 - */ -(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h= -h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, -"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, -e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, -"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ -a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, -C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, -s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, -j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, -toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== --1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; -if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", -b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& -!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& -l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H
a";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), -k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, -scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= -false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= -1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="
t
";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= -"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= -c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); -else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; -if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, -attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& -b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; -c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, -arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= -d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ -c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== -8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== -"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ -d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= -B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== -"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== -0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); -(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; -break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, -q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= -l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, -m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== -true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== -g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]- -0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== -i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; -if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, -g);else if(typeof g.length==="number")for(var p=g.length;n";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); -n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& -function(){var g=k,i=t.createElement("div");i.innerHTML="

";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| -p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= -t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? -function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= -h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): -c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, -2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, -b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& -e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1, -""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; -else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", -prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| -b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length- -1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); -d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, -jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, -zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), -h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); -if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= -d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; -e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/)<[^<]*)*<\/script>/gi, -ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== -"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("
").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& -!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, -getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", -script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| -!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= -false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; -A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", -b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& -c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| -c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= -encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", -[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), -e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); -if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", -3),a,b,d);else{d=0;for(var e=this.length;d=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, -d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* -Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} -var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; -this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| -this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= -c.timers,b=0;b-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, -e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& -c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); -c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ -b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/News/includes/lib/plugins.js b/News/includes/lib/plugins.js deleted file mode 100644 index 9716e4a..0000000 --- a/News/includes/lib/plugins.js +++ /dev/null @@ -1,526 +0,0 @@ -/*! - * jQuery UI 1.8.7 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ -(function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.7",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106, -NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this, -"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position"); -if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f, -"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h, -d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}}); -c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a); -return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;a.target==this._mouseDownEvent.target&&c.data(a.target,this.widgetName+".preventClickEvent", -true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); -;/* - * jQuery UI Draggable 1.8.7 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Draggables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== -"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= -this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top- -this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions(); -d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis|| -this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element, -b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this== -a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]|| -0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0], -this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top- -(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment== -"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[(a.containment=="document"?0:d(window).scrollLeft())-this.offset.relative.left-this.offset.parent.left,(a.containment=="document"?0:d(window).scrollTop())-this.offset.relative.top-this.offset.parent.top,(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"? -0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"), -10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor== -Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop(): -f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY; -if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.leftthis.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/ -b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?e:!(e-this.offset.click.left
').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})}, -stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!= -document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>= -i&&e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable"); -this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this, -arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem= -c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset, -{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment(); -if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start", -a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute"); -if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a, -c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]== -document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate", -null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem): -d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute|| -"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")}, -_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!= -this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a= -this.currentItem.find(":data(sortable-item)"),b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable"); -if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h= -0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width= -this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f}, -update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b= -null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this)); -this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])? -g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive", -g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over= -0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e=0?'&':'?')+q;options.data=null;}else -options.data=q;var $form=this,callbacks=[];if(options.resetForm)callbacks.push(function(){$form.resetForm();});if(options.clearForm)callbacks.push(function(){$form.clearForm();});if(!options.dataType&&options.target){var oldSuccess=options.success||function(){};callbacks.push(function(data){$(options.target).html(data).each(oldSuccess,arguments);});}else if(options.success)callbacks.push(options.success);options.success=function(data,status){for(var i=0,max=callbacks.length;i');var io=$io[0];if($.browser.msie||$.browser.opera)io.src='javascript:false;document.write("");';$io.css({position:'absolute',top:'-1000px',left:'-1000px'});var xhr={responseText:null,responseXML:null,status:0,statusText:'n/a',getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){}};var g=opts.global;if(g&&!$.active++)$.event.trigger("ajaxStart");if(g)$.event.trigger("ajaxSend",[xhr,opts]);var cbInvoked=0;var timedOut=0;setTimeout(function(){var t=$form.attr('target'),a=$form.attr('action');$form.attr({target:id,encoding:'multipart/form-data',enctype:'multipart/form-data',method:'POST',action:opts.url});if(opts.timeout)setTimeout(function(){timedOut=true;cb();},opts.timeout);var extraInputs=[];try{if(options.extraData)for(var n in options.extraData)extraInputs.push($('').appendTo(form)[0]);$io.appendTo('body');io.attachEvent?io.attachEvent('onload',cb):io.addEventListener('load',cb,false);form.submit();}finally{$form.attr('action',a);t?$form.attr('target',t):$form.removeAttr('target');$(extraInputs).remove();}},10);function cb(){if(cbInvoked++)return;io.detachEvent?io.detachEvent('onload',cb):io.removeEventListener('load',cb,false);var operaHack=0;var ok=true;try{if(timedOut)throw'timeout';var data,doc;doc=io.contentWindow?io.contentWindow.document:io.contentDocument?io.contentDocument:io.document;if(doc.body==null&&!operaHack&&$.browser.opera){operaHack=1;cbInvoked--;setTimeout(cb,100);return;}xhr.responseText=doc.body?doc.body.innerHTML:null;xhr.responseXML=doc.XMLDocument?doc.XMLDocument:doc;xhr.getResponseHeader=function(header){var headers={'content-type':opts.dataType};return headers[header];};if(opts.dataType=='json'||opts.dataType=='script'){var ta=doc.getElementsByTagName('textarea')[0];xhr.responseText=ta?ta.value:xhr.responseText;}else if(opts.dataType=='xml'&&!xhr.responseXML&&xhr.responseText!=null){xhr.responseXML=toXml(xhr.responseText);}data=$.httpData(xhr,opts.dataType);}catch(e){ok=false;$.handleError(opts,xhr,'error',e);}if(ok){opts.success(data,'success');if(g)$.event.trigger("ajaxSuccess",[xhr,opts]);}if(g)$.event.trigger("ajaxComplete",[xhr,opts]);if(g&&!--$.active)$.event.trigger("ajaxStop");if(opts.complete)opts.complete(xhr,ok?'success':'error');setTimeout(function(){$io.remove();xhr.responseXML=null;},100);};function toXml(s,doc){if(window.ActiveXObject){doc=new ActiveXObject('Microsoft.XMLDOM');doc.async='false';doc.loadXML(s);}else -doc=(new DOMParser()).parseFromString(s,'text/xml');return(doc&&doc.documentElement&&doc.documentElement.tagName!='parsererror')?doc:null;};};};$.fn.ajaxForm=function(options){return this.ajaxFormUnbind().bind('submit.form-plugin',function(){$(this).ajaxSubmit(options);return false;}).each(function(){$(":submit,input:image",this).bind('click.form-plugin',function(e){var $form=this.form;$form.clk=this;if(this.type=='image'){if(e.offsetX!=undefined){$form.clk_x=e.offsetX;$form.clk_y=e.offsetY;}else if(typeof $.fn.offset=='function'){var offset=$(this).offset();$form.clk_x=e.pageX-offset.left;$form.clk_y=e.pageY-offset.top;}else{$form.clk_x=e.pageX-this.offsetLeft;$form.clk_y=e.pageY-this.offsetTop;}}setTimeout(function(){$form.clk=$form.clk_x=$form.clk_y=null;},10);});});};$.fn.ajaxFormUnbind=function(){this.unbind('submit.form-plugin');return this.each(function(){$(":submit,input:image",this).unbind('click.form-plugin');});};$.fn.formToArray=function(semantic){var a=[];if(this.length==0)return a;var form=this[0];var els=semantic?form.getElementsByTagName('*'):form.elements;if(!els)return a;for(var i=0,max=els.length;i=0?"&":"?")+q;options.data=null}else{options.data=q}var $form=this,callbacks=[];if(options.resetForm){callbacks.push(function(){$form.resetForm()})}if(options.clearForm){callbacks.push(function(){$form.clearForm()})}if(!options.dataType&&options.target){var oldSuccess=options.success||function(){};callbacks.push(function(data){var fn=options.replaceTarget?"replaceWith":"html";$(options.target)[fn](data).each(oldSuccess,arguments)})}else{if(options.success){callbacks.push(options.success)}}options.success=function(data,status,xhr){var context=options.context||options;for(var i=0,max=callbacks.length;i0;var mp="multipart/form-data";var multipart=($form.attr("enctype")==mp||$form.attr("encoding")==mp);if(options.iframe!==false&&(fileInputs||options.iframe||multipart)){if(options.closeKeepAlive){$.get(options.closeKeepAlive,fileUpload)}else{fileUpload()}}else{$.ajax(options)}this.trigger("form-submit-notify",[this,options]);return this;function fileUpload(){var form=$form[0];if($(":input[name=submit],:input[id=submit]",form).length){alert('Error: Form elements must not have name or id of "submit".');return}var s=$.extend(true,{},$.ajaxSettings,options);s.context=s.context||s;var id="jqFormIO"+(new Date().getTime()),fn="_"+id;window[fn]=function(){var f=$io.data("form-plugin-onload");if(f){f();window[fn]=undefined;try{delete window[fn]}catch(e){}}};var $io=$('