Welcome¶

Introduction¶

FoolFuuka was designed to accomplish two different goals: (1) function as an image-based bulletin board software, and (2) provide a functional front-end interface for Asagi. In order to accomplish the latter, you’ll need to prepare and configure your server environment properly.

Features¶

Requirements¶

Web Server¶

You’ll need to install one of the following web servers to allow users to access the web interface:

  • Apache
  • nginx (Recommended)

Database¶

FoolFuuka supports the following database servers:

  • MariaDB 5.5+ (Recommended)
  • MySQL 5.5+

Note

When dealing with large amounts of data, we recommend using the TokuDB storage engine for all board tables which is available with MariaDB. This mainly applies to deployments used to provide a front-end for Asagi and archives.

Git/Composer¶

FoolFuuka utilizes both Git and Composer to manage all of its dependencies, software updates, and web assets.

PHP/HHVM¶

While FoolFuuka is designed to work on PHP 5.4 or newer, it is also compatible with HHVM.

Search Server¶

FoolFuuka requires an additional software to index and serve search results to users. This is achieved with Sphinx Open Source Search Server which must be installed to provide users with search capabilities.

Note

FoolFuuka includes a Sphinx configuration file generator in the web administration interface and should be used to generate a new sphinx configuration file accordingly.

ImageMagick¶

If you plan to use FoolFuuka as an image-based bulletin board, ImageMagick must be installed on the server. The binary files are used to generate and manipulate image files.

Note

You may be required to specify the path for ImageMagick’s convert binary in the administrative panel.

Installation¶

Install¶

Via Composer¶

$ composer create-project foolz/foolfuuka foolfuuka --prefer-source
$ cd foolfuuka
$ composer dump-autoload --optimize

Warning

When asked to remove the VCS files (.git), you must choose N so that the version control system remains intact. This will allow you to perform future upgrades.

Via Source Code¶

$ git clone https://github.com/FoolCode/FoolFuuka foolfuuka
$ cd foolfuuka
$ git checkout 2-2-stable
$ composer install --optimize-autoloader

Upgrading¶

$ git fetch --all
$ git checkout 2-2-stable
$ composer update --optimize

Note

The commands provided above will only upgrade the FoolFuuka code. You may be required to complete some additional steps to completely upgrade FoolFuuka to the next version. Please consult the upgrade guides to ensure that the upgrade process is done properly.

See also

Upgrade Guide

Configuration¶

While most of the configurable settings are exposed through the web administrative panel, there are still a number of settings that can only be modified manually due to security concerns.

Note

In this documentation, we will use dot notations to specify the location of the config key being listed.

FoolFrame¶

These config files are used to manage many of the core settings in the FoolFuuka framework. You can locate these files in the following path after installation: vendor/foolz/foolframe/config/.

Note

We recommend that you copy these config files into and edit them in the following directory: app/foolz/foolframe/config/. The software is designed to load these files instead of the default config files.

cache¶

type
Type:STRING
Default:dummy
format
Type:STRING
Default:smart_json
prefix
Type:STRING
Default:empty
servers
Type:ARRAY
Default:empty

config¶

config.cookie_prefix
Type:STRING
Default:empty
install.installed
Type:BOOLEAN
Default:false
modules.installed
Type:ARRAY

db¶

active
Type:STRING
Default:default
default.driver
Type:STRING
Default:pdo_mysql
default.host
Type:STRING
Default:localhost
default.port
Type:INT
Default:3306
default.dbname
Type:STRING
Default:empty
default.user
Type:STRING
Default:empty
default.password
Type:STRING
Default:empty
default.persistent
Type:BOOLEAN
Default:false
default.prefix
Type:STRING
Default:empty
default.charset
Type:STRING
Default:utf8mb4

foolauth¶

db_connection
Type:STRING
Default:null
table_name
Type:STRING
Default:users
table_autologin_name
Type:STRING
Default:user_autologin
table_login_attempts_name
Type:STRING
Default:user_login_attempts
table_columns
Type:ARRAY
guest_login
Type:BOOLEAN
Default:true
groups
Type:ARRAY
roles
Type:ARRAY
login_hash_salt
Type:STRING
Default:empty
salt
Type:STRING
Default:empty
username_post_key
Type:STRING
Default:username
password_post_key
Type:STRING
Default:password
attempts_to_lock
Type:INT
Default:10

FoolFuuka¶

These config files are used to manage many of the core settings in FoolFuuka that we considered very important and shouldn’t be exposed in the web interface. You can locate these files in the following path after installation: assets/config/.

Note

We recommend that you copy these config files into and edit them in the following directory: app/foolz/foolfuuka/config/. The software is designed to load these files instead of the default config files.

config¶

comment.secure_tripcode_salt
Type:STRING
Default:null

This is the salt used to for secure tripcodes. It is recommend that this salt key be changed when exposed or kept consistent between installations.

media.filecheck
Type:BOOLEAN
Default:true

Checks if the media file exists on the disk. The setting does impact disk performance when enabled due to lstat calls for each file being checked.

Value Effect
true enables the check and returns a generated link based on file existence
false disables the check and returns a full link

foolauth¶

roles
Type:ARRAY

CHANGELOG¶

What’s New in FoolFuuka 2.2.0¶

FoolFuuka 2.2.0 includes a few new features and an overhaul in parts of the code base. The most notable change is the removal of all plugins from the standard distribution which will need to be re-installed manually.

Features¶

  • added GroupByThread option for search results
  • added highlight.js for code highlighting
  • added configurable swiftmailer config file for Mailer

Performance¶

  • changed autoloading of themes and various components to PSR-4
  • removed entire media.filecheck logic

Fixes¶

  • removed trailing forward-slash in default media url
  • reports view now displays board name and view button
  • rewrote sticky/locked toggle logic on archive boards

Misc.¶

  • added additional software hooks in Comment
  • decoupled all plugins from standard distribution
  • moved 4chan specific BBCode to separate plugin
  • replaced StringParser with jBBCode
  • updated FoolFuuka namespace
  • updated FoolFuuka dependencies

User Guide¶

Asagi¶

Requirements¶

Compiling Asagi¶

$ git clone https://github.com/FoolCode/asagi.git
$ mvn package assembly:single

Configuring Asagi¶

Asagi uses a JSON configuration file named asagi.json. An example configuration file is included within thegit repository as asagi.json.example.

Warning

If you are using MySQL/MariaDB as your database server, you must set the character_set_server setting under the [mysqld] section to utf8mb4 in your my.cnf file. This will allow you to properly store multi-byte unicode characters properly.

Note

We recommend that you configure Asagi to use its own database and configure your database server to allow the account created for FoolFuuka to have full access to the Asagi database as well.

Running Asagi¶

$ java -Xmx256m -XX:+UseParNewGC -XX:MaxPermSize=24m -jar asagi.jar

Note

We strongly recommend the usage of screen or tmux with Asagi. Also, you may be required to adjust the Xmx and XX:MaxPermSize values accordingly.

Configuring FoolFuuka¶

Warning

It is very crucial that you configure and run/restart Asagi before adding the board to FoolFuuka. This will allow Asagi to create the board tables properly with some additional steps that aren’t included in FoolFuuka. If this is not done, the board tables will not be populated properly.

You must first configure FoolFuuka to use the Asagi database created in the previous steps. This can be done by following the steps listed below:

  1. Access the FoolFuuka Administrative Panel
  2. Navigate to Preferences under the Boards section
  3. Set the Boards Database field to the same database name used in the asagi.json config file
  4. Save your changes

Note

The steps listed above only need to be completed once.

In order to access the boards being archived with Asagi, you will need to add the boards to FoolFuuka by following the steps listed below:

  1. Access the FoolFuuka Administrative Panel
  2. Navigate to Manage under the Boards section
  3. Click “Add Board”
  4. Fill out the required fields properly
  5. Check the “Is this an archived board?” checkbox
  6. Click “Submit” to add the board to the database

Note

You will need to repeat the steps listed above each time you wish to add a board archived by Asagi.

Upgrade Guide¶

From 2.0 to 2.1¶

As of 2.1.0, we’ve deprecated the original FoolFuuka installer repository and changed the folder structure of the FoolFuuka installations.

Backup¶

You will need to create a backup of the following folders or move them to a new location:

  • app/
  • public/foolfuuka/boards/

Note

Depending upon your configuration, you may not need to backup the public/foolfuuka/boards/ directory.

Obtain the Latest Code¶

You can install the latest stable version of 2.1 by using one of the following methods:

Via Composer¶
$ composer create-project foolz/foolfuuka foolfuuka
$ cd foolfuuka
$ composer dump-autoload --optimize
Via Source Code¶
$ git clone https://github.com/FoolCode/FoolFuuka foolfuuka
$ cd foolfuuka
$ git checkout 2-1-stable
$ composer install --optimize
Copy App Files and Data¶

You will need to restore the following folders from the backup to the same locations:

  • app/
  • public/foolfuuka/boards/

Note

Depending upon your configuration, you may not need to restore the public/foolfuuka/boards/ directory.

From 2.1 to 2.2¶

Backup¶

We recommend that you create a backup of the following folders or move them to a safe location:

  • app/
  • public/foolfuuka/boards/

Note

Depending upon your configuration, you may not need to backup the public/foolfuuka/boards/ directory.

Obtain the Latest Code¶
$ cd /path/to/foolfuuka
$ git checkout 2-2-stable
$ composer update --optimize
Update Core Framework Config Files¶

You are required to update the app/foolz/foolframe/config/config.php file to match the following config provided:

<?php
return array(
    'config' => array(
        'cookie_prefix' => 'foolframe_NEW_',
    ),
    'install' => array(
        'installed' => true,
    ),
    'modules' => array(
        'installed' => array(
            'foolframe' => array(
                'context' => '\\Foolz\\FoolFrame\\Model\\Context',
                'namespace' => 'foolz/foolframe',
            ),
            'foolfuuka' => array(
                'context' => '\\Foolz\\FoolFuuka\\Model\\Context',
                'namespace' => 'foolz/foolfuuka',
            ),
        ),
    ),
);
Restart Services¶

You may need to restart the following services:

  • PHP/HHVM
  • Apache/Nginx/etc.

Developer Guide¶

Code Documentation¶

REST API¶

Index¶

GET /_/api/chan/index/

Property Type Description Required
board string This is the shortname for the board. Y
page integer The page number of the index. Y
{
  "2": {
    "omitted": 10,
    "images_omitted": 10,
    "op": {
      "<POST OBJECT>"
    },
    "posts": [
      {
        "<POST OBJECT>"
      }
    ]
  },
  "1": {
    "omitted": 10,
    "images_omitted": 10,
    "op": {
      "<POST OBJECT>"
    },
    "posts": [
      {
        "<POST OBJECT>"
      }
    ]
  }
}
Thread¶

GET /_/api/chan/thread/?board=dev&num=1

Property Type Description Required
board string This is the shortname for the board. Y
num integer This is the post number of the thread. Y
latest_doc_id integer This is the latest doc_id used as a starting point. N
last_limit integer This limits the results to the last x posts. N
{
  "1": {
    "op": {
      "<POST OBJECT>"
    },
    "posts": {
      "2": {
        "<POST OBJECT>"
      },
      "3": {
        "<POST OBJECT>"
      }
    }
  }
}
Post¶

GET /_/api/chan/post/?board=dev&num=1

Property Type Description Required
board string This is the shortname for the board. Y
num mixed This is the post number. Y
{
  "doc_id": "1",
  "poster_ip": "1111111111",
  "num": "1",
  "subnum": "0",
  "thread_num": "1",
  "op": "1",
  "timestamp": "1339024666",
  "timestamp_expired": "0",
  "capcode": "A",
  "email": null,
  "name": "Anonymous",
  "trip": null,
  "title": null,
  "comment": "COMMENT DATA HERE",
  "poster_hash": "fUSBgQ2y",
  "poster_country": null,
  "deleted": "0",
  "sticky": "0",
  "comment_processed": "COMMENT DATA HERE",
  "title_processed": "",
  "name_processed": "Anonymous",
  "email_processed": "",
  "trip_processed": "",
  "poster_hash_processed": "fUSBgQ2y",
  "fourchan_date": "6\/6\/12(Wed)23:17",
  "comment_sanitized": "COMMENT DATA HERE",
  "poster_country_name_processed": null,
  "media": {
    "op": "1",
    "media_id": "1024",
    "spoiler": "0",
    "preview_orig": "13390246665411s.jpg",
    "preview_w": "216",
    "preview_h": "250",
    "media_filename": "8211205.jpg",
    "media_w": "742",
    "media_h": "860",
    "media_size": "130990",
    "media_hash": "P2asAleYuUWVvEFBotaaxA==",
    "media_orig": "13390246665411.jpg",
    "exif": null,
    "total": "1",
    "banned": "0",
    "media": "13390246665411.jpg",
    "preview_op": "13390246665411s.jpg",
    "preview_reply": null,
    "media_status": "normal",
    "safe_media_hash": "P2asAleYuUWVvEFBotaaxA",
    "preview_orig_processed": "13390246665411s.jpg",
    "media_filename_processed": "8211205.jpg",
    "media_hash_processed": "P2asAleYuUWVvEFBotaaxA==",
    "media_link": "https:\/\/0-media-cdn.foolz.us\/ffuuka\/board\/dev\/image\/1339\/02\/13390246665411.jpg",
    "remote_media_link": "https:\/\/0-media-cdn.foolz.us\/ffuuka\/board\/dev\/image\/1339\/02\/13390246665411.jpg",
    "thumb_link": "https:\/\/0-media-cdn.foolz.us\/ffuuka\/board\/dev\/thumb\/1339\/02\/13390246665411s.jpg"
  }
}

Software Hooks¶

Plugin¶
Foolz\Plugin\Plugin::execute#<plugin-name>¶
->setObject($plugin)
->setParam('context', $this->getContext())
Foolz\FoolFrame\Model\Plugin::install#<plugin-name>¶
->setParam('context', $this->getContext())
->setParam('schema', $sm->getCodedSchema())
FoolFrame¶
Foolz\FoolFrame\Controller\Admin::before#var.sidebar¶
->setObject($this)
->setParam('sidebar', [])
Foolz\FoolFrame\Model\Context::handleConsole#obj.app¶
->setObject($this)
->setParam('application', $application)
Foolz\FoolFrame\Model\Context::handleWeb#obj.afterAuth¶
->setObject($this)
->setParam('route_collection', $this->route_collection)
Foolz\FoolFrame\Model\Context::handleWeb#obj.routing¶
->setObject($this)
->setParam('route_collection', $this->route_collection)
Foolz\FoolFrame\Model\Context::handleWeb#obj.context¶
->setObject($this)
Foolz\FoolFrame\Model\Context::handleWeb#obj.request¶
->setObject($this)
->setParam('request', $request)
Foolz\FoolFrame\Model\Context::handleWeb#obj.response¶
->setObject($this)
->setParam('request', $request)
Foolz\FoolFrame\Model\Preferences::load#var.preferences¶
->setObject($this)
->setParam('preferences', $this->preferences)
Foolz\FoolFrame\Model\SchemaManager::forge#var.ignorePrefix¶
->setObject(new static())
->setParam('prefixes', $prefixes)
Foolz\FoolFrame\Model\SchemaManager::forge#var.tables¶
->setObject(new static())
->setParam('tables', $tables)
Foolz\FoolFrame\Model\System::getEnvironment#var.environment¶
->setParam('environment', $environment)
FoolFuuka¶
Foolz\FoolFuuka\Model\Comment::processComment#var.greentext¶
->setParam('html', $html)
Foolz\FoolFuuka\Model\Comment::processComment#var.originalComment¶
->setObject($this)
->setParam('comment', $this->comment->comment)
Foolz\FoolFuuka\Model\Comment::processComment#var.processedComment¶
->setObject($this)
->setParam('comment', $this->comment->comment)
Foolz\FoolFuuka\Model\Comment::processCommentBBCode#var.definitions¶
->setObject($this)
->setParam('definitions', $definitions)
Foolz\FoolFuuka\Model\CommentInsert::insert#obj.captcha¶
->setObject($this)
Foolz\FoolFuuka\Model\CommentInsert::insert#obj.afterInputCheck¶
->setObject($this)
Foolz\FoolFuuka\Model\CommentInsert::insert#obj.comment¶
->setObject($this)
Foolz\FoolFuuka\Model\Context::loadRoutes#obj.beforeRouting¶
->setObject($this)
->setParam('route_collection', $route_collection)
Foolz\FoolFuuka\Model\Context::loadRoutes#var.collection¶
->setParam('default_suffix', page)
->setParam('suffix', page)
->setParam('controller', 'Foolz\\FoolFuuka\\Controller\\Chan::*')
Foolz\FoolFuuka\Model\Context::loadRoutes#obj.afterRouting¶
->setObject($this)
->setParam('route_collection', $route_collection)
Foolz\FoolFuuka\Model\Media::insert#var.media¶
->setParam('dimensions', $dimensions)
->setParam('file', $file)
->setParam('name', $name
->setParam('path', $path)
->setParam('hash', $hash)
->setParam('size', $size)
->setParam('time', $time)
->setParam('media_orig', $media_orig)
->setParam('preview_orig', $preview_orig)
Foolz\FoolFuuka\Model\Media::insert#exec.createThumbnail¶
->setObject($this)
->setParam('is_op', $is_op)
->setParam('media', $media)
->setParam('thumb', $thumb)
->setParam('thumb_width', $thumb_width)
->setParam('thumb_height', $thumb_height)
->setParam('exec', $exec)
Foolz\FoolFuuka\Model\MediaFactory::forgeFromUpload#var.config¶
->setParam('ext_whitelist', [])
->setParam('mime_whitelist', [])
Foolz\FoolFuuka\Model\RadixCollection::structure#var.structure¶
->setParam('structure', $structure)
Foolz\FoolFuuka\Model\RadixCollection::preload#var.radixes¶
->setObject($this)
->setParam('preloaded_radixes', $this->preloaded_radixes)

Contribute¶

Coding Guidelines¶

FoolFuuka follows the PSR-0 and PSR-0 coding standards. In addition to these standards, the guidelines listed below must be followed as well:

  • Function and Control Structure opening { MUST BE on a seperate line

IRC Channel¶

We have an IRC channel on the IRCHighWay network that can be used to discuss issues, feature requests, and various other related topics at #fooldriver.

Issue Tracker¶

You can find our issue tracker at our FoolFuuka GitHub repository.