-
- 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 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 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 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 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-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 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 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 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 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 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.
-
-
- 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:
-
-
-
- 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):
-
-
-
0.30%
-
0.50%
-
0.70%
-
0.83%
-
0.90%
-
0.96%
-
-
-
-
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)
-
- 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:
-
-
-
- A screenshot of the second, "Driver" tab:
-
-
-
- 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
-
- 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:
-
-
-
- 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:
-
-
-
JACK: ~/.log/jack/jackdbus.log
-
A2J: ~/.log/a2j/a2j.log
-
LASH: ~/.log/lash/lash.log
-
LADISH: ~/.log/ladish/ladish.log
-
-
-
-
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
-
- 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:
-
-
-
- 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
-
- 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
-
-
-
- Another screenshot, now running under Windows 8:
-
-
-
- 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)
-
- 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)
-
-
-
- A screenshot of the second, "Tools" tab:
- (The screenshots are clickable, which will start their respective tools)
-
-
-
- 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)
-
-
-
-
-
Download
-
- Cadence is available in the KXStudio repositories and ArchLinux AUR (both with 'cadence' package name).
-
-
- ArchLinux (AUR)
-
-
- Debian/Ubuntu (via KXStudio repositories)
-
- 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)
-
- 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:
-
-
-
Single-client: (JACK driver only)
- Same as Multi-client, except that all JACK ports belong to a single master client.
- This is needed when a setup doesn't support multi-client JACK apps, such as LADISH.
-
-
Multi-client: (JACK driver only)
- Every single plugin is exposed as a new JACK client. Audio and MIDI ports are registered as needed.
-
-
Rack:
- Plugins are processed in order, from top to bottom.
- Plugins with non-stereo audio channels are not supported, but a forced-stereo option is available for Mono ones.
-
-
Patchbay:
- Modular patchbay mode, just like in JACK Multi-client and many other modular applications.
- Every plugin gets its own canvas group and ports allowing you to interconnect plugin audio and MIDI.
-
-
-
-
-
The Interface
-
- By default Carla uses its own internal theme, a screenshot of it follows along with some plugins:
-
- 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:
-
-
-
- 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)
-
- 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:
-
-
-
- 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:
-
-
-
- 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:
-
-
-
Unchecked (None): no eye-candy;
-
Partially (Small): applies drop-shadow to the boxes, this is the default;
-
Checked (Full): box drop-shadow, fade-in/out animations and line glow;
-
-
- (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:
-
-
-
Unchecked (None): disable all anti-aliasing;
-
Partially (Small): applies only to the lines, this is the default;
-
Checked (Full): apply anti-aliasing everywhere;
-
-
- 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)
-
- 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:
-
-
-
-
-
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)
-
- 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:
-
-
-
-
-
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)
-
- 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:
-
-
-
-
-
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 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:
-
-
-
-
-
-KDE3 (Trinity)
-
-
-
-
-KDE4
-
-
-
-
-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:
-
Set KDE color-scheme using the 'KXStudio.colors' provided
-
Set KDE widget style to QtCurve
-
Configure KDE QtCurve style, and load the 'KXStudio.qtcurve' config
-
Set Gtk2 theme to KXStudio (KXStudio decoration, QtCurve style, Oxygen icons)
-
Set Qt4/Qt3 style to QtCurve (using qtconfig-qt4/qt3)
-
-
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
-
Audio Session management through LADISH
-
One-app-to-rule them all (Cadence)
-
-
-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 ;)
-
- 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:
-
-
-
A Graphic designer that can make Gtk3 themes
-
Anyone that would like to make some good video tutorials
-
Non-Ubuntu users to beta-test the Cadence tools
-
-
-
- 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).
-
- This page contains a list of things left to do for KXStudio.
-
-
-
-
- Tasks for common people (not Team restricted):
-
-
-
KXStudio Dark Metacity theme (based on Ambiance)
-
KXStudio Gtk3 Theme port (In progress)
-
- Work has already been done for this, but it's still far from finished.
- The current theme uses the solidity-gtk3 engine.
- It's available in the latest KXStudio Artwork release.
-
-
Make kxstudio-menu module work on all systems (In progress)
-
- kxstudio-menu has been proven to work on Gnome2, KDE3, KDE4 and XFCE4.
- It may not work on LXDE, needs testing (any LXDE users here?).
-
-
QJackCtl needs to support proper jackdbus save/load, so it shares configuration with Cadence and laditools
- 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:
-
- 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.
-
- 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
-
-
The live session user name is "kxstudio" and has no password.
-
Because Carla is still unfinished, FeSTige is currently on the DVD (and thus in the default install).
- This is only temporary, FeSTige is no longer being developed and will be soon replaced by Carla functionality.
-
Sometimes the keyboard layout is not set-up correctly on the live session. This can be manually fixed by running:
- setxkbmap pt(replace 'pt' by the relevant keyboard layout/language).
-
The guitarix version included in the DVD has CPU optimizations enabled and may not work on older systems.
- This can be fixed by updating its package during the live session.
-
The list of packages installed on the Live-DVD is available
- here for 32bit and
- here for 64bit.
-
-
-
-
-
Current 12.04.1 Notes
-
-
The Carla tool is unfinished, and as such it will show a warning every-time you start it.
- We're working hard to make it complete and stable as soon as possible, so stay tuned.
-
Only KDE4 is officially supported now. XFCE will also work but your experience may not be as great.
- Other desktops are unsupported at this point.
-
Ubuntu is focused at PulseAudio and doesn't provide good raw/ALSA mixers by default if you're Desktop is not KDE.
- On such cases you should disable the PulseAudio mixer and use another tool (such as kmix, qamix, volti or alsamixer).
- You may need to reconfigure the multimedia global shortcuts to use the new mixer
-
Some applications and websites don't work nicely with dark themes, which KXStudio uses by default.
- This is not a bug in the theme(s) but rather upstream (ie, app and website authors).
- We encourage users to report such issues upstream so they can be fixed for everyone using dark themes.
-
Synaptic is now used for handle package management in KXStudio, and as such users won't receive update notifications anymore.
- Users should open synaptic and do system updates on a regular basis.
- 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.
-
- 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
-
-
The live session user name is "kxstudio" and has no password.
-
Sometimes the keyboard layout is not set-up correctly on the live session. This can be manually fixed by running:
- setxkbmap pt(replace 'pt' by the relevant keyboard layout/language).
-
The list of packages installed on the Live-DVD is available
- here for 32bit and
- here for 64bit.
-
-
-
-
-
Current 12.04.3 Notes
-
-
Ubuntu is focused at PulseAudio and doesn't provide good raw/ALSA mixers by default if you're Desktop is not KDE.
- On such cases you should disable the PulseAudio mixer and use another tool (such as kmix, qamix, volti or alsamixer).
- You may need to reconfigure the multimedia global shortcuts to use the new mixer
-
Some applications and websites don't work nicely with dark themes, which KXStudio uses by default.
- This is not a bug in the theme(s) but rather upstream (ie, app and website authors).
- We encourage users to report such issues upstream so they can be fixed for everyone using dark themes.
-
The linux 3.8 kernel has a small regression for USB-Audio interfaces, forcing users to use a high JACK buffer-size value.
- If this affects you, consider installing linux-lowlatency-3.2, -3.5 or -3.11 which do not have the issue.
- 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.
-
- 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
-
-
The live session user name is "kxstudio" and has no password.
-
Sometimes the keyboard layout is not set-up correctly on the live session. This can be manually fixed by running:
- setxkbmap pt(replace 'pt' by the relevant keyboard layout/language).
-
The list of packages installed on the Live-DVD is available
- here for 32bit and
- here for 64bit.
-
-
-
-
-
Current 12.04.3 Notes
-
-
Ubuntu is focused at PulseAudio and doesn't provide good raw/ALSA mixers by default if you're Desktop is not KDE.
- On such cases you should disable the PulseAudio mixer and use another tool (such as kmix, qamix, volti or alsamixer).
- You may need to reconfigure the multimedia global shortcuts to use the new mixer
-
Some applications and websites don't work nicely with dark themes, which KXStudio uses by default.
- This is not a bug in the theme(s) but rather upstream (ie, app and website authors).
- We encourage users to report such issues upstream so they can be fixed for everyone using dark themes.
-
The linux 3.8 kernel has a small regression for USB-Audio interfaces, forcing users to use a high JACK buffer-size value.
- If this affects you, consider installing linux-lowlatency-3.2, -3.5 or -3.11 which do not have the issue.
- 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
-
-
Some applications and websites don't work nicely with dark themes, which KXStudio uses by default.
- This is not a bug in the theme(s) but rather upstream (ie, app and website authors).
- We encourage users to report such issues upstream so they can be fixed for everyone using dark themes.
-
The KXStudio GTK3 theme is unfinished. Applications that use GTK3 might appear slightly broken.
-
-
-
-
-
Pre-installed applications
-
-
- The list of pre-installed applications in the ISO follows, not listing audio plugins.
-
- 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
-
-
The live session user name is "kxstudio" and has no password.
-
Synaptic is used for handling package management in the Live-DVD, users do not receive package update notifications.
- Users should open synaptic (or a similar tool) and do system updates on a regular basis.
-
Neither PulseAudio or Wine are included in the Live-DVD, they need to be installed if required.
- Because Firefox now requires PulseAudio, it will not produce any sound by default on this Live-DVD.
-
-
Sometimes the keyboard layout is not set-up correctly on the live session. This can be manually fixed by running:
-
setxkbmap pt
- (replace 'pt' by the relevant keyboard layout/language).
-
-
Installation for (U)EFI systems will fail due to missing packages if not connected to the internet.
- If you need to install on such systems, make sure to connect to the internet before starting the installer.
-
-
-
-
-
-
-
-
Current 14.04.5 Notes
-
-
Some applications and websites don't work nicely with dark themes, which KXStudio uses by default.
- This is not a bug in the theme(s) but rather upstream (ie, app and website authors).
- We encourage users to report such issues upstream so they can be fixed for everyone using dark themes.
-
The KXStudio GTK3 theme is unfinished. Applications that use GTK3 might appear slightly broken.
- 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
-
-
TODO: test 18.04 and write relevant notes here
-
-
-
-
-
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)
-
- 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
-
-
The live session user name is "kxstudio" and has no password.
-
Wine is not included in the Live-DVD, it needs to be installed if required.
- A meta-package called kxstudio-meta-wine was created or it, for convenience. Just open Synaptic and install it.
-
-
Sometimes the keyboard layout is not set-up correctly on the live session. This can be manually fixed by running:
-
setxkbmap pt
- (replace 'pt' by the relevant keyboard layout/language).
-
-
Installation for (U)EFI systems will fail due to missing packages if not connected to the internet.
- If you need to install on such systems, make sure to connect to the internet before starting the installer.
-
-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:
-
-
-
-
-
-
-
-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.
-
-
-
-
-
-
-
-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:
-
-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.
-
-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.
-
-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'.
-
-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.
-
-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.
-
-
-
First, resize existing systems that you want to keep, if you have any
-
-
Create a new “extended” partition in the empty space
-
-
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.
-
-
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
-
-
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
-
-
-
-
If your drive is large enough, you may keep extra space free to later create partitions for additional GNU/Linux systems on the same machine
-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.
-
-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 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:
-
-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:
-
-
-
LightScribe support — LightScribe is a proprietary technology that uses specially made CDs and DVDs to allow users to burn direct-to-disc labels.
-
-
-
-
LinuxDSP is a proprietary developer of quality Linux-native audio plugins. Most of the included plugins are limited demo versions, both proprietary and also not free of charge. The developer supports other FLOSS projects, however, and is active in the GNU/Linux audio community.
-
-
-
-
Loomer is another developer of cross-platform proprietary audio plugins. They have ported several of their offerings to GNU/Linux. Aspect is among the most powerful Linux-native softsynths available. All Loomer plugins come as demos until a license is purchased.
-
-
-
-
Pianoteq is a piano instrument synthesizer with exceptionally advanced features and sound quality. The included software also runs in demo mode until a license is purchased.
-
-
-
-
REAPER is a Windows program that has official support to run in WINE. A fully native version for Linux is in the works although it will likely remain non-free. REAPER runs as a fully functional demo which simply reminds users to buy a modestly-priced license after a trial period. Many people coming from Mac or Windows may be familiar with REAPER and want to continue using it with KXStudio.
-
-
-
-
Renoise is a Linux-native “tracker” style music production program. It has a dedicated user base and offers many features. The demo is functional with the exception of song and instrument rendering.
-
-
-
-
SunVox is another Linux-native “tracker” style music program. It's known for being available for a wide range of platforms including Windows, Linux, Mac OS X, Windows Mobile, PalmOS, Maemo, Meego, iOS and Android. Although SunVox is proprietary, the desktop version used in KXStudio does not have any limitations.
-
-
-
-
VST plugin support — The VST format is itself proprietary, but specific plugins may be either FLOSS or proprietary. VST plugins may be either Windows-based (these function via the Free Wine software) or Linux-native. Several FLOSS programs support VST plugins. All included VST plugins, whether FLOSS or proprietary, are in the non-free repository. You can also download Windows VSTs from internet sources and use them within KXStudio, although this is not officially supported.
-
-
-
-
-
-
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.
-
-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.
-
-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.
-
-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.
-
-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
-
-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:
-
-
-
-
-
-
-
-
-
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.
-
-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
-
-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
-
-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
-
-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
-
-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:
-
-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)
-
-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.
-
-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:
-
-
-
Number of inputs
-
-
Number of outputs
-
-
Connect to hardware (auto-connect to JACK hardware ports)
-
-
Autostart server (start JACK automatically if not already running)
-
-
Fixed buffersize (if off, the host is allowed to change the current JACK buffersize on the fly)
-
-
Preferred buffersize (if fixed buffersize is off, WineASIO attempts to use this value on startup)
-
-
-
-
-
-
-
-
-
-
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.
-
-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
-
-
-
Start REAPER then choose Preferences, the bottom option in the Options menu, or just push CTRL+P
-
-
Choose Device under the Audio section from the list to the left of the Preferences window
-
-
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.
-
-
Apply, OK, done!
-
-
-
-
-
-
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”.
-
- 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:
-
-
-
kxstudio-meta-all
-
kxstudio-meta-audio
-
kxstudio-meta-audio-plugins
-
-
-
kxstudio-meta-audio-plugins-collection
-
-
-
or
-
-
-
kxstudio-meta-audio-plugins-ladspa
-
kxstudio-meta-audio-plugins-dssi
-
kxstudio-meta-audio-plugins-lv2
-
kxstudio-meta-audio-plugins-vamp
-
kxstudio-meta-audio-plugins-vst
-
-
-
-
kxstudio-meta-graphics
-
kxstudio-meta-video
-
-
kxstudio-meta-restricted-extras
-
kxstudio-meta-wine
-
-
-
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.
-
- 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.
-
- 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):
-
-
-
kxstudio-meta-all
-
-
kxstudio-meta-audio
-
-
kxstudio-meta-audio-plugins
-
-
kxstudio-meta-audio-plugins-dssi
-
kxstudio-meta-audio-plugins-ladspa
-
kxstudio-meta-audio-plugins-lv2
-
kxstudio-meta-audio-plugins-vamp
-
kxstudio-meta-audio-plugins-vst
-
-
-
kxstudio-meta-graphics
-
kxstudio-meta-video
-
-
kxstudio-meta-codecs
-
kxstudio-meta-restricted-extras
-
kxstudio-meta-non-free
-
-
- 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.
-
- 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:
-
-
-
kxstudio-kernel-generic
-
kxstudio-kernel-generic-pae (32bit only)
-
kxstudio-kernel-lowlatency
-
kxstudio-kernel-lowlatency-pae (32bit only)
-
kxstudio-kernel-realtime (10.04 or 12.04)
-
kxstudio-kernel-realtime-pae (10.04 or 12.04, 32bit only)
-
-
- 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.
-
- 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.
-
- 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.
-
- 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!
-
- MacOS Downloads:
-
- Carla2 (version 2.0-RC4 for macOS 10.8 or higher)
-
-
- Windows Downloads:
-
- Cadence (32bit, version 0.8.1)
-
- Carla2 (32bit, version 2.0-RC4)
-
- Carla2 (32bit version 2.0-RC4, No-SSE build for old PCS)
-
- Carla2 (64bit, version 2.0-RC4)
-
-
-
-
-
-
-
Source Code Releases
-
- Software developed by the KXStudio Team, released as source tarball so that distros other than Ubuntu (or advanced users) can pick it up.
- If you're running a Debian or Ubuntu based system, please use the KXStudio Repositories instead.
-
- By using QtCurve, our theme can perfectly match Gtk2, Qt3, KDE3, Qt4 and KDE4 applications.
- See the KXStudio Artwork section for screenshots of various Desktop Environments using the KXStudio theme.
-
-
-
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
-
-
carla-vst: Add Ardour workaround for its 'Analysis' window
-
carla-vst: Fix typo leading to buffer size of 1 during plugin activation
-
Fix for some stupid plugins messing up with global signals (restore original signals after creating plugin)
-
Fix dry/wet for VST plugins (by creating extra buffer for inline processing)
-
Fix crash in RtAudio when ALSA soundcard is listed but not available
-
Fix crash on JACK buffer size changes in patchbay mode
-
Fix crash when directly loading vst shell plugins (carla-single or drag&drop dll file)
-
Fix loading multiple exported LV2 plugins (always copy full carla-plugin binary when exporting)
-
Fix missing transport information when Carla is not jack transport master
-
Fix opening a few VST2 UIs (we give up trying to follow VST spec, always assume UI opens nicely)
-
Fix plugin bridges not working under Fedora (RT threads were able to be setup, but not started)
-
Automatically terminate wine bridges if main carla dies
-
Calculate VST2 ppqPos in a more reliable way
-
Do not set up RtAudio in "hog device" mode
-
Do not build external plugins in debug or strict build
-
Handle more sources of VST2 automation via audioMasterAutomate
-
Handle worst-case scenario of carla-plugin buffer size being too low
-
-
- 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:
-
-
-
Fix glBars and ProM plugins not being built and installed
-
Kars: Added release and volume parameters
-
Kars: Remove its useless UI
-
Nekobi: Add enum values for waveform parameter
-
Remove modguis, they are maintained in a separate repo
-
-
-
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:
-
-
-
Fix samplerate property in lv2 UIs
-
Fix (implement) parent window for about dialogs for MacOS and Windows
-
Add get/set scaling to Window
-
Add option to automatically scale plugin UIs
-
Allow plugin UIs to be user-resizable, test with info and meters example
-
Implement basic effGetParameterProperties in vst plugins (boolean, integer and log flags)
-
Implement midi out
-
Implement enumerator style of parameters
-
Implement LV2-trigger-type parameters
-
Implement Shift-click to reset sliders
-
Report supported LV2 options in generated ttl
-
Render VST2 parameter-text integer, boolean and enum parameters
-
Rework calculation of VST transport/time info
-
Set _NET_WM_WINDOW_TYPE for our X11 windows
-
-
- 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.
-
- > 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
-
-
Fix bridge-lv2-x11 crash when manually started from CLI
-
LV2: Don't prefer plugin bridges for certain hardcoded plugins (Calf, ir.lv2 and v1 series)
-
VST: Do not call plugin effEditIdle on update display opcode, fixing crashes for a few plugins
-
-
-
- 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:
-
-
-
If v1 plugin series are compiled with a Qt version different than the one Carla is using, expect a crash on load or soon afterwards
-
Calf plugin UIs will be missing their graphs by default, unless you disable running plugin UIs in bridge mode in Carla settings
-
-
- 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.
-
-
- > 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
-
-
Fix build against fluidsynth 2.0
-
Fix build on Haiku OS
-
Fix build with external plugins enabled but no OpenGL available
-
Fix detection of old Windows dll plugins
-
Fix dynamic/split process cycle for plugin bridges
-
Fix internal plugins receiving wrong frame position on split buffers
-
Fix program changes coming through as bank changes in MIDI output
-
Fix a possible race condition in plugin code
-
Fix some warnings triggered by gcc-8
-
Fix LV2 plugins with UI feedback ports in bridge mode not receiving feedback events
-
Fix macOS specific note visible in settings when not running macOS
-
libjack: Fix applications that register clients right after being started
-
-
-
Usability fixes
-
-
Always show keyboard in plugin edit dialog if plugin has midi inputs
-
Always expand user home path (~/) when loading project from CLI
-
Don't try to find binary type of certain plugins when loading project (avoid assertions)
-
Use executable basename on jack apps as name when initial name is empty
-
libjack: Catch window close when possible, and hide it instead closing entire application
-
libjack: Implement basic session management via SIGUSR1 signal
-
-
-
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:
-
-
-
LinuxSampler API being overcomplicated
-
SFZ handling not very reliable
-
Licensing issues
-
-
-
- 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.
-
-
-
Allow control output parameters to go out of bounds, thus displaying the correct value
-
Automatically restart plugin bridges when plugin is re-activated, using last saved state
-
Don't allow to disable jack transport if running in multi-client mode
-
Don't close and re-open VST plugin UIs on show/hide
-
Don't change any engine settings if it currently running
-
Don't list lv2 plugins that are not supported
-
Don't make Windows or macOS plugin UIs resizable for now
-
Implement loop-mode for audio-file plugin, turn it on by default
-
Implement support for buffer size changes in RtAudio JACK driver, and ignore JACK sample rate mismatch
-
Implement SF3 support (SF2 files with OGG audio files instead of raw WAV)
-
Force fftw thread-safe mode when starting Carla as standalone
-
Plugins with more than 2 audio ports can now be loaded in rack mode (the extra ports are just ignored)
-
Save and restore BPM with a project
-
Save and restore last used BPM, if not loading a project
-
-
-
Fixes
-
- Besides the ones already mentioned for Windows, we also have:
-
-
-
Big push to get transport working correctly
-
General fixes against dynamic buffer sizes
-
Several fixes to UI size and UI bridges under macOS
-
Fix all PNGs that triggered libpng warnings
-
Fix canvas rubberband being invisible after a canvas refresh
-
Fix embedded UI covering window controls under certain hosts (in a Qt5 Linux build)
-
Fix switching plugin positions in plugin mode
-
-
-
Notes for developers and packagers
-
-
Base python scripts are no longer installed in dist-packages
-
Carla front-end code was moved to its own folder
-
FluidSynth version 1.1.7 is now required for soundfont support
-
UI bridges can now be started from CLI with just the plugin URI
-
New CarlaNativePlugin header and library exported, exposes Carla's Rack and Patchbay internals to 3rd party applications
-
-
- 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:
-
-
-
Add confirmation dialog for quitting Carla
-
Add confirmation dialog for "Remove All" and "New File" actions
-
Add internal MIDI Channel A/B plugin
-
Add semitones parameter to internal midi-transpose plugin
-
Implement move up/down plugins in rack (right-click menu)
-
Implement LV2 UI port notifications to feedback messages to UI
-
Implement more libjack stubs, Catia now loads inside Carla :)
-
Transport controls are now considered stable and always enabled, no longer in experimental settings
-
Disable ableton-link and audio kits search UI elements if not built/enabled
-
Do not capture logs if running in nogui mode
-
Do not use or check for kVstParameterUsesIntegerMinMax VST property
-
Do not lockup on close in case audio driver stops working
-
Export LV2 window is now a simple combo-box, making it more usable
Fix mouse position offset of Carla-embed mouse events
-
Fix processing of internal plugins with multi MIDI inputs
-
Fix crash when closing a session containing bridges with Ctrl+C
-
Fix patchbay/graph to work with variable buffer sizes
-
Fix some issues regarding integer parameter control
-
Fix controlling logarithmic parameters with MIDI CC
-
Fix "MIDI CC 0x01" not selectable in some systems
-
Fix loading of VST plugin parameters and LV2 state for plugin bridges
-
Fix carla-single usage under ladish
-
Fix file dialog filter of the internal MIDI file plugin
-
-
-
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 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.
-
- 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.
-
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 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.
-
- 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:
-
-
-
Added artwork and license to about dialog
-
Added carla-rack no-midi-out mode as plugin
-
Allow drag&drop of plugin binaries into Rack view
-
Add "prevent bad plugin behaviour" option (experimental, Linux only)
-
Auto-detect wine-prefix for plugin bridges
-
Expand usable MIDI keyboard keys a little (Z-M plus Q-P for 2 full octaves and 5 extra keys)
-
Implement parameter text for plugin bridges
-
Implement "Manage UIs" option for macOS and Windows
-
Place more parameters per tab in editor dialog
-
Show active peaks and enable keyboard for carla-rack group in canvas
-
Knobs are now controlled in a linear way
-
Previous experimental plugins removed, and carla-zynaddsubfx no longer exported
-
Rack view can handle integeter knobs properly
-
Save and restore canvas positions (standalone only for now)
-
-
-
Special Notes
-
-
Carla as plugin and Carla-Control are still not available for Windows, likely won't be done for v2.0.
-
-
-
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
-
- 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:
-
-
-
Plugin bridges
-
Wine options
-
Force-stereo mode
-
Canvas eye-candy
-
Canvas with OpenGL
-
-
- 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!
-
- > 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
-
- 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.
-
-
-
-
-
-
-
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.
-
-
-
-
-
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. ;)
-
-
-
-
-
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).
-
-
-
-
-
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.
-
-
-
-
-
-
-
ProM
-
- projectM is an awesome music visualizer.
- This plugin makes it work as an audio plugin (LV2 and VST).
-
-
-
-
glBars
-
- This is an OpenGL bars visualization plugin (as seen in XMMS and XBMC/Kodi).
- Adapted from the
- jack_glbars
- project by Nedko Arnaudov.
-
-
-
-
-
-
- > 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.
-
- 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 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
-
- 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 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
-
-
Add carla-jack-single/multi startup tools
-
Add 16 channel and 2+1 (sidechain) variant to Carla-Patchbay plugins
-
Add new custom menu when right-clicking empty rack & patchbay areas
-
Add command-line option for help and version arguments
-
Add command-line option to run Carla without UI (requires project file)
Implement initial latency code, used for aligned dry/wet sound for now
-
Implement support for VST shell plugins under Linux
-
Implement sorting of LV2 scale points
-
Allow to scan and load 32bit AUs under Mac OS
-
Allow using the same midi-cc in multiple parameters for the same plugin
-
Allow Carla-VST to be built with Qt5 (Linux only)
-
Bypass MIDI events on carla-rack plugin when rack is empty
-
Find plugin binary when saved filename doesn't exist
-
Force usage of custom theme under Mac OS
-
New option to wherever put UIs on top of carla (Linux only)
-
Make canvas draggable with mouse middle-click
-
Make it possible to force-refresh scan of LV2 and AU plugins
-
Plugin settings (force stereo, send CC, etc) are now saved in the project file
-
Renaming plugins under JACK driver mode now keeps the patchbays connections
-
Update modgui code for latest mod-ui, supports control outputs now
-
Lots and lots of bug fixes.
-
-
- There will still be 1 more beta release before going for a release candidate, so expect more cool stuff soon!
-
-
-
Special Notes
-
-
Carla as plugin is still not available under Windows, to be done for the next beta.
-
-
-
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.
-
- > 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 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.
-
-
-
-
-
-
-
-
-
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 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
-
-
-
LinuxSampler code has been reworked and it's working better, it now exposes 2 output parameters.
-
The plugin bridge code has been reworked; bridges are much more stable and MIDI-out is working.
-
NSM code has also been reworked, testers welcome.
-
OSC ports can be static by using CARLA_OSC_TCP_PORT and CARLA_OSC_UDP_PORT environment variables.
-
Time panel can be shown/hidden as needed.
-
DISTRHO-based internal plugins are back, specifically 3BandEQ/Splitter, PingPongPan, Nekobi, MVerb, VectorJuice and WoobleJuice.
-
carla-single script is back, allowing you to quickly test and run all plugins.
-
Carla as plugin allows new, open and save-as (export) menu actions.
-
Start of new midi-sequencer plugin, still experimental and Linux-only for now.
-
MIDI file internal plugin now saves the contents, so you can share projects without worrying if the file exists on the other system.
-
Added 6 basic parameters to the ZynAddSubFX internal plugin.
-
New MIDI channel filter plugin.
-
LV2 and AU plugins are cached and automatically updated when needed, no need for scanning.
-
Patchbay mode is now working for non-JACK drivers.
-
Carla saves internal and external connections, specially useful in patchbay mode.
-
Lots and lots of bug fixes.
-
-
-
Special Notes
-
-
Renaming plugins currently is not safe (unless using Rack mode).
-
GIG/SF2/SFZ skin still to be done, and some others...
-
Plugin bridges only work on Linux right now. They used to be working for OSX but stopped due to a OS limitation.
-
Windows 64bit builds a shows small console windows when discovering plugins. This is not intended and will hopefully be fixed 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.
-
-
-
-
-
- > 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
-
- 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.
-
-
-
-
-
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
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 (MacOS only)
-
- AU plugins are working in Carla now.
- Carla's plugin compatibility increases once more.
-
-
-
-
-
-
-
-
-
New and updated skins
-
- There's a new OpenAV-style plugin slot skin.
- Calf and ZynFX have been updated.
- More to come soon.
-
-
-
-
-
-
-
-
-
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
-
-
New time panel added, but it's very incomplete.
-
LV2 plugin discovery is now automatic, but without plugin checks or testing.
-
LV2 plugins are fully working on MacOS and Windows, including their native UIs (Cocoa and HWND respectively).
-
-
- 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)
-
-
-
All DPF and JUCE-based internal plugins were removed to reduce code size and complexity, they will be re-introduced later
-
AU plugin support is available on MacOS, but the discovery mechanism fails to find them
-
Linux release has support for bridging Window plugins using Wine (32bit and 64bit).
-
Linux 32bit release will not load 64bit plugins even if ran on a 64bit system
-
MacOS Carla-Rack LV2 plugin fails to show UI
-
MacOS and Windows do not support native widgets in LV2 yet (Cocoa and HWND, respectively)
-
MacOS release is 64bit only but it can load 32bit plugins
-
Windows 64bit build doesn't provide GIG and SFZ support, use the 32bit build if you need those
-
Windows builds do not support bridges (ie, 32bit plugins on a 64bit Carla) or Carla as plugin
-
-
- 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:
-
-
-
Dexed
-
KlangFalter
-
MVerb
-
Nekobi
-
Obxd
-
PitchedDelay
-
-
- Additionally we made a new plugin - ProM
- - a music visualizer as audio plugin based on projectm.
-
- > 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!
-
- 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
-
-
-
-
-
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
-
- 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.
-
-
-
-
-
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
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
-
-
Qt5 ready (already used in Windows builds)
-
Save and restore canvas connections
-
LV2 CV ports and Worker extension are now implemented, allowing to load ams-lv2 and setBfree among other plugins
-
VST3 and AU plugin support
-
-
- 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:
-
-
-
Load entire Carla projects - rack or patchbay - as a single plugin in the graph (avoiding clutter);
-
Carla itself as an LV2 plugin;
-
-
- 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 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.
-
-
- Apps:
-
Add AriaMaestosa, Giada and Petri-Foo to the DVD and default install
-
Upgrade Cadence to the beta1 release (lots of fixes!)
-
Fully up-to-date apps and plugins (as of 30/12/2012)
-
Use KDE 4.9.4 on the Live-DVD (repositories now have 4.9.5)
-
Use Firefox-KDE PPA on the Live-DVD
-
-
- Desktop/Theme:
-
Add kxstudio-text plymouth (used when no gpu drivers are available)
-
Fix plymouth Live-DVD "eject disk now" text not visible (and any other labels/info)
-
Change KDE desktop theme to slim-glow (backported latest release from KDE 4.10)
-
Change cursor theme to oxy-zion
-
Disable KDE bouncing cursor by default
-
Use Claudia-Launcher instead of Klaudia in KDE kickoff (start menu)
-
-
- Settings:
-
Auto-disable PulseAudio respawn
-
Set default asoundrc file to snd-aloop
-
Set default jack prio to 85
-
Use ALSA-Audio bridge instead of PulseAudio (no longer installed by default)
-
-
- Welcome Wizard:
-
Add theme screenshot button
-
Add theme font size option
-
Auto-register 64bit WineAsio too (done in 'wine stuff' step)
-
Don't update user theme to KXStudio by default
-
Disable theme updates if not running KDE4 or XFCE
-
-
- 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!
-
- > 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:
-
-
-
-
-
-
-
-
-
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") }
-
-
-
-
-
-{% block navigation %}
- {% for action, nav in navigation | items %}
- {% if nav.show %}
-
- {% 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 }
-
-
-
-
-
".__("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)."
]+)?>|^)/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 '
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.
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.
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!
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 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.
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.
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:
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 <br />'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.
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.
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 %}
-
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.
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/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 %}
-
'",
- $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
".__("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.= "
\n\t
".__("Move the .htaccess file from the original Chyrp directory, and change the RewriteBase line to reflect the new website location.")."
\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:
-
-
-
-
-
-