Exim local delivery (06.06.2017)
We need to deliver mail to our "local" domain through external server.
  driver = dnslookup
  domains = *

Instagram open api requests (09.03.2017)
Parse instagram account and get all photos
$ig = json_decode(file_get_contents("https://www.instagram.com/kevin/media/"));
while($ig->more_available) {
  foreach($ig->items as $item) {
    echo $item->id."<br>";
    echo "<img src=".$item->images->standard_resolution->url."><br>";
    echo $item->caption->text."<br>";
  $ig = json_decode(file_get_contents("https://www.instagram.com/kevin/media/?max_id=".$item->id));
Get photos details by hashtag (filter auditory)
$ig = json_decode(file_get_contents("https://www.instagram.com/explore/tags/friday/?__a=1"));
while($ig->tag->media->page_info->has_next_page) {
  foreach($ig->tag->media->nodes as $item) {
    echo $item->id." ".$item->owner->id."\n";
  $ig = json_decode(file_get_contents("https://www.instagram.com/explore/tags/friday/?__a=1&max_id=".$ig->tag->media->page_info->end_cursor));
Let's encrypt free ssl (17.02.2017)
So comodo ssl is not so free, I changed it to letsencrypt.

on centos6:
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
./certbot-auto --apache

certbot can't read my vhosts configuretion:
No names were found in your configuration files. Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c' to cancel)
So we'll do it by hands. Enter 'c' in promt. Script will generate certificate files then.
My httpd.conf vhost part:
SSLCertificateKeyFile /etc/letsencrypt/keys/0001_key-certbot.pem
SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain.com/fullchain.pem
Comodo free SSL (09.10.2016)
How to get and install Comodo free ssl sertificate on linux.
yum install mod_ssl openssl
openssl req -nodes -newkey rsa:2048 -keyout domain.key -out domain.csr -subj "/C=GB/ST=Yorks/L=York/O=Kodilo Ltd./OU=IT/CN=domain.com"
Register Comodo account and follow instructions.
In the end get two certificate files: domain.ca-bundle and domain.crt, place it to /etc/ssl/certs folder.
In /etc/httpd/conf.d/ssl.conf edit or create new VirtualHost on port 443 and add following settings to it:
SSLEngine on
SSLCertificateKeyFile /etc/ssl/domain.key
SSLCertificateFile /etc/ssl/certs/domain.crt
SSLCertificateChainFile /etc/ssl/certs/domain.ca-bundle
Google Calendar events on the SyncML device (28.06.2016)
Get Google Calendar events on the SyncML compatible phone.

After Google stoped it’s SyncML service in 2013 there’s no free simple solution to synchronize the Calendar with SyncML device (like Nokia s40 in my case). Another reason to setup own server is outdated technology so last online sync services may go down soon.
We will install Funambol SyncML server on linux and use Google Calendar PHP API to import Calendar events to Funambol mysql database.

Funambol installation instruction:

Install Funambol
wget -O funambol-10.0.3-x64.bin https://sourceforge.net/projects/funambol/files/bundle/v10/funambol-10.0.3-x64.bin/download
chmod +x funambol-10.0.3-x64.bin

Download and insert mysql-connector-java:
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.39.tar.gz
tar -zxvf mysql-connector-java-5.1.39.tar.gz
cp ./mysql-connector-java-5.1.39/mysql-connector-java-5.1.39-bin.jar  /opt/Funambol/tools/jre-1.6.0/jre/lib/ext/
cp ./mysql-connector-java-5.1.39/mysql-connector-java-5.1.39-bin.jar  /opt/Funambol/pim-listener/lib/
cp ./mysql-connector-java-5.1.39/mysql-connector-java-5.1.39-bin.jar  /opt/Funambol/inbox-listener/lib/

Change /opt/Funambol/ds-server/install.properties:

Create mysql database:
mysql> create database funambol;
mysql> GRANT ALL PRIVILEGES ON funambol.* TO 'funambol'@'localhost'  IDENTIFIED BY 'funambol';

Make init script to start Funambol as service (founded here). We don’t actually need all services from the instruction, also it’s memory consuming, so we’ll start only funambol-server.

cd `dirname $0`
FUNAMBOL_HOME=`(cd /opt/Funambol ; pwd)`

if [ ! -d $FUNAMBOL_HOME/config ]; then
# maybe we are in Funambol/tool/bin

# Setting the JAVA_HOME to the JRE in the bundle if not set or if not correctly set
if [ -z "$JAVA_HOME" ]; then
export JAVA_HOME=$FUNAMBOL_HOME/tools/jre-1.5.0/jre
if [ ! -f "$JAVA_HOME/bin/java" ]; then
export JAVA_HOME=$FUNAMBOL_HOME/tools/jre-1.5.0/jre

if [ -z "$JAVA_HOME" ]; then
echo “Please, set JAVA_HOME before running this script.”
exit 1

if [ ! -f "$JAVA_HOME/bin/java" ]
echo “Please set JAVA_HOME to the path of a valid jre.”

export J2EE_HOME=${FUNAMBOL_HOME}/tools/tomcat
export CATALINA_HOME=${FUNAMBOL_HOME}/tools/tomcat


export LANG=en_US.utf-8

cd ${J2EE_HOME}/bin

case $1 in

# Run DS Server
sh $FUNAMBOL_HOME/bin/funambol-server start > /dev/null

# Shutdown Tomcat
sh $FUNAMBOL_HOME/bin/funambol-server stop > /dev/null
echo “usage: $0 [start|stop]”

Now we should see Web Demo client on http://yourserver.name:8080/ (admin/sa, guest/guest) and can synchronize a cellphone with following parameters:
Server name: http://yourserver.name:8080/funambol/ds
Username: guest
Password: guest
Sync what: Contacts, Calendar, Tasks, Notes (as needed)
Databases names:
Contacts: card
Calendar: event
Tasks: task
Notes: note

Get Google Calendar PHP SDK:
git clone -b v1-master https://github.com/google/google-api-php-client.git

Here is little changed quick start example of getting 10 future events from default calendar (read this instruction). Added import data to funambol database.
Before using this script we should create an application with appropriate scope and place client_secret.json file to our directory.
$db_server_name = "localhost";
$db_username = "user";
$db_password = "password";
$db_name = "funambol";

$conn = new mysqli($db_server_name, $db_username, $db_password, $db_name);
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
$conn->query("SET NAMES 'utf8'");

function add_event($dstart, $dend, $subject, $body, $gid, $all_day) {
  global $conn;
  $sql = "SELECT * FROM fnbl_pim_calendar WHERE gid='".$gid."'";
  $result = $conn->query($sql);
  if ($result->num_rows > 0) {
    $sql = "UPDATE fnbl_pim_calendar
        userid = 'guest',
        categories = 'MEETING',
        last_update = '".time()."000',
        status = 'N',
        type = 1,
        rec_type = -1,
        all_day = '".$all_day."',
        dstart = '".$dstart."',
        dend = '".$dend."',
        subject = '".$subject."',
        body = '".$body."'
      WHERE gid = '".$gid."'";
    $result = $conn->query($sql);
  else {
    $sql = "INSERT INTO fnbl_pim_calendar
        userid = 'guest',
        categories = 'MEETING',
        last_update = '".time()."000',
        status = 'N',
        type = 1,
        rec_type = -1,
        all_day = '".$all_day."',
        dstart = '".$dstart."',
        dend = '".$dend."',
        subject = '".$subject."',
        body = '".$body."',
        gid = '".$gid."'";
    if(!$result = $conn->query($sql))
      printf("Errormessage: %s\n", $conn->error);

set_include_path(get_include_path() . PATH_SEPARATOR . './google-api-php-client/src');

require_once './google-api-php-client/src/Google/autoload.php';

define('APPLICATION_NAME', 'Google Calendar API PHP Quickstart');
define('CREDENTIALS_PATH', './calendar-php-quickstart.json');
define('CLIENT_SECRET_PATH', './client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/calendar-php-quickstart.json
define('SCOPES', implode(' ', array(

if (php_sapi_name() != 'cli') {
  throw new Exception('This application must be run on the command line.');

* Returns an authorized API client.
* @return Google_Client the authorized client object
function getClient() {
  $client = new Google_Client();

  // Load previously authorized credentials from a file.
  $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
  if (file_exists($credentialsPath)) {
    $accessToken = file_get_contents($credentialsPath);
  } else {
    // Request authorization from the user.
    $authUrl = $client->createAuthUrl();
    printf("Open the following link in your browser:\n%s\n", $authUrl);
    print 'Enter verification code: ';
    $authCode = trim(fgets(STDIN));

    // Exchange authorization code for an access token.
    $accessToken = $client->authenticate($authCode);

    // Store the credentials to disk.
    if(!file_exists(dirname($credentialsPath))) {
      mkdir(dirname($credentialsPath), 0700, true);
    file_put_contents($credentialsPath, $accessToken);
    printf("Credentials saved to %s\n", $credentialsPath);

  // Refresh the token if it's expired.
  if ($client->isAccessTokenExpired()) {
    file_put_contents($credentialsPath, $client->getAccessToken());
  return $client;

* Expands the home directory alias '~' to the full path.
* @param string $path the path to expand.
* @return string the expanded path.
function expandHomeDirectory($path) {
  $homeDirectory = getenv('HOME');
  if (empty($homeDirectory)) {
    $homeDirectory = getenv("HOMEDRIVE") . getenv("HOMEPATH");
  return str_replace('~', realpath($homeDirectory), $path);

// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);

// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
  'maxResults' => 10,
  'orderBy' => 'startTime',
  'singleEvents' => TRUE,
  'timeMin' => date('c'),
$results = $service->events->listEvents($calendarId, $optParams);

if (count($results->getItems()) == 0) {
  print "No upcoming events found.\n";
} else {
  print "Upcoming events:\n";
  foreach ($results->getItems() as $event) {
  $start_date = $event->start->date; //The date, in the format "yyyy-mm-dd", if this is an all-day event.
  $end_date = $event->end->date;
  $start_time = $end_time = "";
  $all_day = 1;
    if($event->start->dateTime) {
    $all_day = 0;
    $start = explode("T",$event->start->dateTime);
    $start_date = $start[0];
    $start_time = explode("+", $start[1]);
    $start_time = $start_time[0];
    if($event->end->dateTime) {
    $end = explode("T",$event->end->dateTime);
    $end_date = $end[0];
    $end_time = explode("+", $end[1]);
    $end_time = $end_time[0];
  if(!$end_date) $end_date = $start_date;
  $dstart = $start_date." ".$start_time;
  $dend = $end_date." ".$end_time;
  $subject = $event->getSummary();
  $body = $event->getDescription() ? $event->getDescription() : " ";
  $gid = $event->getId();
  //echo $dstart, $dend, $subject, $body, $gid, "\n";
      add_event($dstart, $dend, $subject, $body, $gid, $all_day);

After executing the script we can see added events in Funambol web interface and sync it to our phone.
adm, PHP
Highlight searched substring with php (23.06.2016)
Simple text highlighter on PHP, useful to mark search results.

$search = $_GET["search"]; //exists check ommited
$text = "Content in which to search here";

//i modifier to ignore case, u for utf-8 (cyrillic supported)
$search ? preg_replace("/".($search)."/iu", '<i>\0</i>' , $text) : $text;
Dynamic load of content elements by ajax (23.06.2016)
Dynamic load of content elements (post, articles etc) by ajax in endless scrolling  
<div class="content">
  <div class="element"></div>
  <div class="element"></div>


//useful to get GET-parameters from url, which may be used in sql WHERE
function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split('&');
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        if (decodeURIComponent(pair[0]) == variable) {
            return decodeURIComponent(pair[1]);

//elements counter, used in sql LIMIT operator on backend
var more = 10;

//send query to backend when we scrolled down to end of page
$(window).on("scroll", function() {
  var scrollHeight = $(document).height();
  var scrollPosition = $(window).height() + $(window).scrollTop();
  if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
      $.post( "/response.php", {more: more, search: getQueryVariable("search")}, function( data ) {
        if(data) {
          more += 10;

In this example we got prepared formatted content from backend.
Ajax, JavaScript
Yet another simple jquery slider (30.03.2016)
Very easy to customize jquery slider with fixed width slides.

$( ".left_arr" ).click(function() {
  if(parseInt($( ".line" ).css("margin-left")) > (($( ".line .slide" ).length-1)*-400)) {
    $( ".fbline" ).animate({
    "margin-left": "-=400",
    }, 1000, function() {
$( ".right_arr" ).click(function() {
  if(parseInt($( ".line" ).css("margin-left"))<0) {
    $( ".line" ).animate({
    "margin-left": "+=400",
    }, 1000, function() {


<div class="container">
  <div class="line">
    <div class="slide">1</div>
    <div class="slide">2</div>
    <div class="slide">3</div>


  width: 300px;
  padding: 0 50px;
  display: inline-block;
  text-align: center;
.container {
  margin: 0 80px;
  overflow: hidden;
.line {
  display: inline-block;
  width: 9999px;
Sorting any structure in PHP (03.02.2016)
With this example we can sort any kind of data - strings, arrays, objects etc. just changing required atribute in strcmp call.

function cmp($a, $b)
    return strcmp($a->created, $b->created);
usort($arr, "cmp");
AIX useful comands (02.12.2015)
cfgmgr - update fc-devices (~ forcelip + devfsadm)
lsdev -C -c disk - list disk type devices
lsattr -El hdisk - device attributes
chdev -l hdisk -a queue_depth=8;chdev -l hdisk -a max_transfer=0x200000 - tune lun for Veritas SF

Tapes (IBM Tape Library):
installp -acXd ~distrib/Atape/Atape. Atape.driver - IBM tape drive driver
lsdev -C -c tape - now drives should display as IBM 3580 Ultrium Tape Drive

If cfgmgr don't make new rmt devices after cleaning, but all is correct:
rmdev -Rl fscsi5 - now fscsi and it's children are shown as Defined
cfgmgr -vl fscsi5

for i in {0..19}; do rmdev -dl rmt$i; done - remove rmt-devices

lsdev -p fscsi2 - child devices of controller (luxadm -e dump_map)
lscfg -vl fcs5 | grep Address - how adapter wwn

Dynamic tracking between fscsi and rmt should be off:
chdev -l fscsi0 -a dyntrk=no -P

Expand (extend) local filesystem:
lslv hd10opt | grep -i group - in which disk group it is
lsvg rootvg | grep -i free - free space in group
chfs -a size=5G /opt - extend TO size
Pure JavaScript Ajax form handler example (27.11.2015)
Here we send all form fields as json to backend on form submit.

$("#form").submit(function(e) {
  var xhr = new XMLHttpRequest();
  var params = $('#form').serialize();
  xhr.open('POST', '/mail.php', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
       if(xhr.status == 200) {
       $('#form').css("display", "none");
Chroot sftp (30.07.2015)
Как дать пользователю доступ только по sftp и запереть его в одном каталоге.

useradd -m -d /home/user user
chown root:root /home/user
chmod 755 /home/user


#Subsystem      sftp    /usr/libexec/openssh/sftp-server
Subsystem   sftp   internal-sftp

Match User user
        X11Forwarding no
        AllowTcpForwarding no
        ForceCommand internal-sftp
        ChrootDirectory /home/user

Как пробросить в данный chroot недоступные каталоги:

mount --bind /some/folder /home/user/folder
Сбой авторизации MODX Revo (06.05.2015)
Одна из многих причин, почему пользователя может не пускать в админку modx - повреждение таблицы modx_sessions. Чинится легко с помощью phpmyadmin в общем списке отмечаем галкой эту таблицу, затем выбираем "С отмеченными -> Восстановить таблицу".
Если после неудачных логинов успел заблокироваться пользователь, также необходимо выставить нули в полях blocked, blockeduntil, blockedafter таблицы modx_user_attributes.
Textarea undo redo (20.11.2014)
Заведем объект для хранения истории контента поля ввода:
var buffer = {
  content: [],
  add: function(el) {
    this.counter = this.current = this.content.push(el)-1;
  undo: function() {
    if(this.current>0) this.current-= 1;
    return this.content[this.current];
  redo: function() {
    if(this.current<this.counter) this.current+= 1;
    return this.content[this.current];
  counter: 0,
  current: 0
И установим обработчик событий:
window.onload = (function() {
  document.getElementById("content").onkeydown = function(e) {
    if(this.value!=buffer.content[buffer.current]) buffer.add(this.value);
    if (e.keyCode == 90 && e.ctrlKey) { //ctrl+z
      this.value = buffer.undo();
    if (e.keyCode == 89 && e.ctrlKey) { //ctrl+y
      this.value = buffer.redo();
Наброски по UMI CMS (20.11.2014)

Верстка должна быть XML-валидной!
Дебаг включается в config.ini:
enabled = "1"
show-backtrace = "1"

Вывести контент в базовом шаблоне (<xsl:template match="/">):
<xsl:apply-templates select="result" />

Шаблон вывода этого контента, записывается или подключается после закрытия базового шаблона:

<xsl:template match="result[@module = 'content'][@method = 'content']">
    <xsl:value-of select=".//property[@name = 'h1']/value" />
  <div id="text">
    <xsl:value-of select=".//property[@name = 'content']/value" disable-output-escaping="yes" />

Вызов макроса:

<xsl:value-of select="document('udata://custom/getChildren/')" disable-output-escaping="yes" />

макросы предлагается записывать в /classes/modules/custom.php

Список ссылок на дочерние страницы:

public function getChildren(){
  $current_page_id = cmsController::getInstance()->getCurrentElementId();
  $hierarchy = umiHierarchy::getInstance();
  $childs = $hierarchy->getChilds($current_page_id);
  $res = "";
  foreach ($childs as $child_id=>$value) {
    $page = $hierarchy->getElement($child_id);
    $title = $page->name;
    $path = $hierarchy->getPathById($child_id);
    $res.= "<li class='child'><a href='".$path."'>".$title."</a></li>";
  if($res!="") $res = "<ul class='child_list'>".$res."</ul>";
  return $res;  

Пример по XSLT-макросам
Постинг через Facebook API v3 (18.11.2014)
Использую старую версию Facebook PHP SDK (v.3.2.3), поскольку для четверки нужен имеющийся не везде PHP 5.4.
require 'facebook-php-sdk/src/facebook.php';

$facebook = new Facebook(array(
  'appId'  => '$appId',
  'secret' => '$secret',

// Get User ID
$user = $facebook->getUser();
Костыль со stackoverflow, перенаправляющий нас на авторизацию, если она не подхватилась:
if ($user <> '0' && $user <> '') { /*if valid user id i.e. neither 0 nor blank nor null*/
  try {
  // Proceed knowing you have a logged in user who's authenticated.
    $user_profile = $facebook->api('/me');
  } catch (FacebookApiException $e) { /*sometimes it shows user id even if user in not logged in and it results in Oauth exception. In this case we will set it back to 0.*/
    $user = '0';
else {/*If user id isn't present just redirect it to login url*/
  header("Location:{$facebook->getLoginUrl(array('req_perms' => 'email,offline_access'))}");
Попытаемся запостить сообщение на стену группы:
$facebook->api('/$group_id/feed/', 'post', array(
    'message' => 'I want to display this message on my wall',
  'link' => 'http://kodilo.ru',
  'picture' => 'http://images.boomsbeat.com/data/images/full/1893/facebook-jpg.jpg',
  'name' => 'The name of the link',
  'caption' => 'Caption of the link',
  'description' => 'Description of the link'

Facebook PHP SDK
Решение проблемы с user=0
Динамический viewport (15.11.2014)
Screen есть у мобильников и планшетов, проверять его можно не ожидая [window].onload

<meta name="viewport" id="vp">
if(screen.width<=480) document.getElementById("vp").setAttribute("content", "width=480");
Постинг через API vk.com (13.11.2014)
Авторизация для JS-приложений (будут работать с разных ip и без редиректа токена):
Параметр offline дает нам "вечный" токен до смены авторизовавшим его пользователем пароля. Токен будет получен в hash-части url.

Пример вызова метода:

PHP и другие серверы: метод с получением code, затем token - херня и, хоть он до сих пор опубликован в документации, не работает. Токен все равно надо получать через браузер, как в примере выше.
$query = file_get_contents("https://api.vk.com/method/wall.post?owner_id=$public_id&message=Тест&v=5.26&access_token=$token")
JavaScript, PHP, API
Отключаем снятие ресурсов с публикации в modx revo (11.11.2014)
По умолчанию в modx при достижении даты снятия с публикации у ресурса помимо галки "опубликованности" (published) обнуляются также дата публикации (publishedon), дата автоматической публикации (pub_date) и дата снятия с публикации (unpub_date), что не очень удобно, т.к. полезно знать даты, когда ресурс был опубликован, даже когда он более не актуален. Примером может быть размещенный на сайте календарь - нам могут быть интересны уже прошедшие события, а плодить новые поля для указания дат, на мой взгляд, излишне.
Проверка наступления unpub_date производится в двух местах:
при ручном сохранении материала - в файле /core/model/modx/processors/resource/update.class.php, комментируем следующие строки:
public function setUnPublishDate() {
а также в менеджере кэша: /core/model/modx/modcachemanager.class.php:
public function autoPublish(array $options = array()) {
  //$publishingResults['unpublished']= $this->modx->exec("UPDATE $tblResource SET published=0, publishedon=0, pub_date=0, unpub_date=0 WHERE unpub_date IS NOT NULL AND unpub_date < {$timeNow} AND unpub_date > 0");
Modx, CMS, PHP
Конфиги Apache (17.10.2014)
Направить все url на один обработчик
<Directory /var/www/html>
        AllowOverride All
Options +FollowSymLinks # для работы mod_rewrite
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f # если файл по ссылке не существует
RewriteCond %{REQUEST_FILENAME} !-d # или папка
RewriteRule .* index.pl [L]

Заставить httpd исполнять perl:

yum install perl-libwww-perl perl-MailTools perl-MIME-Lite perl-CGI perl-DBI 'perl(HTML::Template)' mod_perl

DirectoryIndex .. index.pl
AddHandler cgi-script .cgi .pl
<Directory /var/www/html>
        Options ExecCGI

Обширный пост на хабре
Произведение, состоящее из чисел множителей (19.08.2014)
Поиск подобных пар чисел:
для множителей менее ста.

Руководство по Brainfuck для новичков [8] (16.08.2014)
К началу

7 Ответы на частые вопросы

7.1 Что такое эзотерический язык программирования?

Разработка таких языков производится в качестве эксперимента, реализации нестандартных подходов к разработке ПО, ну или просто для смеха. Для решения серьезных задач эзотерические языки, как правило, не подходят.

7.1.1 Является ли таковым Brainfuck?

Разумеется. Вряд ли вы когда-либо в практических целях станете использовать программу на Brainfuck. Даже при создании простых алгоритмов, проще использовать С, куда легко портировать команды языка. Сложностей при разработке добавляет плохая читаемость исходного кода, который неминуемо превращается в кашу при попытке написать что-либо полезное, а также ограниченные возможности ввода-вывода.

7.2 Это самый маленький язык программирования?

7.2.1 И да...

Взглянув на набор команд кажется, что больше из языка при сохранении функциональности вырезать ничего нельзя. Мы имеем
  Присвоения: + и -
  Ввод-вывод: , и .
  Цикл и ветвление: [ и ]
  Перемещение по памяти < и >
Мы можем представить себе и более компактные языки, часто являющиеся наследниками Brainfuck, например
  с ограниченной функциональностью (к примеру, входные данные уже должны содержаться в памяти);
  с урезанным набором значений (Bitfuck работает с битами вместо байтов)
Все это делает программу еще более громоздкой.

7.2.2 И нет...

Вдохновившись Brainfuck энтузиасты делают относительно успешные попытки создания языков с еще меньшим набором команд.
Boolfuck использует однобитные ячейки памяти, что позволяет сократить команды присвоения с двух до одной - достаточно только инверсии бита (команда *).
Аналогичный ему Bitfuck также состоит из семи команд, однако, четыре из них записываются двумя символами. Всего для записи программы требуется 4 символа, чем авторы и гордятся.
Можно также избавиться от ввода-вывода, объединить по две команды в одну и оставить всего четыре реальных команды:
  [ начать цикл
  ] завершить цикл
  ( передвинуться влево и инвертировать бит
  > передвинуться вправо

Для дальнейшего упрощения предлагается не разделять данные и инструкции в памяти. В абстрактной машине с архитектурой URISC (Ultimate Reduced Instruction Set Computer) используется одна команда, чье поведение определяется состоянием битов под указателем. Вариантом такой команды является BitBitJump. Инструкция работает с тремя адресами - копирует бит по первому адресу во второй адрес и перемещает указатель к третьему адресу, который становится “первым” и так далее.

7.3 Как выучить Brainfuck?

Также, как и любой другой язык - чтением документации (благо, ее можно целиком усвоить за считанные минуты), примеров и программ, и практикуясь самостоятельно.

Можно прислушаться к экспертному мнению
Руководство по Brainfuck для новичков (16.08.2014)
[Текущее состояние перевода]

Final version 2012-08-11
Начало перевода 2014-07-18

Дословного перевода у меня не получилось, кое-где имеются отступления от текста. Также потребовалось изменить ряд примеров и исправить ошибки в них.

Введение. История создания языка.
Команды. Абстрактная модель.
Пример программы - ввод-вывод.
Hello World!
Простые конструкции. Арифметика.
Условный переход.
Ответы на частые вопросы.

Мой интерпретатор Brainfuck на js
Я намеренно не стал добавлять выход из цикла по инструкции "]" при нулевой текущей ячейке, по-моему, эта проверка лишняя, ведь мы все равно вывалимся из цикла в его начале.
Brainfuck, JavaScript
Руководство по Brainfuck для новичков [6] (16.08.2014)
К началу

6.7 If

В Brainfuck отсутствует условный оператор if, однако, для ветвления можно использовать особенность цикла [ ] и запускать его только один раз. Примеры в основном основаны на http://esolangs.org/wiki/brainfuck_algorithms

6.7.1 If (x != 0)

Проверка значения на ноль - самое простое для реализации условие, поскольку если число больше нуля, цикл запустится сам по себе, нам необходимо только обеспечить выход из него после первого прохода. Для этого подготовим временную ячейку с нулевым значением и перейдем на нее в конце цикла.

+>[-]<    (1)0
[+>]      2(0)
Если значение #0 не равно нулю, увеличить #0, перейти на #1

6.7.2 If (x != 1)

Для сравнения с числом необходимо вспомнить пример с поиском искомого значения в цикле. Перед началом цикла отнимем данное число из проверяемого, а затем восстановим его значение.
Руководство по Brainfuck для новичков [5] (16.08.2014)
К началу

6 Простые конструкции

6.1 Поиск нуля

Алгоритм нахождения первой нулевой ячейки справа от текущей:
6.1.1 Описание

Как было показано ранее, цикл [ ] выполняется до тех пор, пока значение текущей ячейки при начале цикла не равно нулю. При выполнении команды > мы перемещяемся вправо до тех пор, пока не достигнем ячейки, содержащей ноль.

6.1.2 Поиск других значений

Аналогично можно искать что-либо еще:

1: -[+>-]+
2: --[++>--]++ Описание
До начала цикла мы уменьшаем значение текущей ячейки на искомое число. Если мы достигли нуля, считаем, что нашли необходимую ячейку, цикл пропускается и мы восстанавливаем значение текущей ячейки. Иначе, уже в цикле, восстанавливаем значение, продвигаемся вправо, уменьшаем значение и т.д.
Подобной конструкцией очень легко запустить бесконечный цикл, если искомого значения в памяти не найдется.

6.2  Перемещение содержимого одной ячейки в другую

Поскольку ячейки памяти в Brainfuck имеют непосредственное влияние на алгоритм, перемещение значения в другую ячейку может оказаться полезным. Так можно просто размножить значение, получить сумму текущей ячейки и соседней, а также управлять поведением цикла [ ].
Следующая программа переместит значение текущей ячейки в последующую:
++>+++<    (2)3
[->+<]>    0(5)
1. Вычтем единицу из значения первой ячейки
2. Переместимся ко второй
3. Добавим единицу
4. Вернемся к первой ячейке
Цикл будет продолжаться, пока значение первой ячейки не станет нулем.
Путем небольших изменений можно изменить направление переноса или разнести значение по нескольким ячейкам.

6.3  Сложение

Описанный выше процесс перемещения деструктивен, поскольку он обнуляет значение первой ячейки. Чтобы его восстановить, сохраним даное значение во временной ячейке памяти, а затем разнесем его по первым двум.
Следующая программа добавит значение текущей ячейки к последующей, используя третью ячейку для временного хранения:
++>+++<      (2)3
[->>+<<]       (0)32
>>[-<+<+>>]<     2(5)0
Сперва переместим значение первой ячейки в третью. Затем значение третьей ячейки в первую и вторую.

6.4 Копирование

Копирование значения одной ячейки в другую можно разложить на две операции - очистку целевой ячейки, присвоение ей значения исходной ячейки:
++>+++<         (2)3
>[-]               2(0)
<[->+>+<<]         (0)22
>>[-<<+>>]<        2(2)
6.5 Вычитание

Вычитание, как можно было предположить, от сложения отличается только знаком:
6.6 Умножение

Умножение - это повторяющееся сложение, а значит, можно воспользоваться приобретенным опытом. Поскольку первый множитель будет уменьшаться при каждом проходе, необходимо сохранить его значение во временной ячейке.
Умножим число 2 в ячейке #0 на 3 в ячейке #1 (пример взят отсюда)
          I проход  II проход
++>+++<      (2)3    
[>        2(3)    1(3)3
[>+>+<<-]      2(0)33  1(0)63
>>[<<+>>-]    233(0)  136(0)
<<<-]        (1)33    (0)36
>>            03(6)

Далее - Условный переход
Руководство по Brainfuck для новичков [4] (16.08.2014)
К началу

5.2 Hello World

Из множества книг по языкам программирования вам хорошо известна программа “Hello World”. Как правило, это простейшая программа, производящая видимый результат - вывод символов на экран. Однако, для Brainfuck это задача не из легких, т.к. для вывода каждого символа мы должны присвоить его ASCII-код текущей ячейке используя только имеющиеся операторы.
В отступление от текста, реализуем задачу в простейшем виде, используя единственную ячейку памяти, меняя ее значение и выводя результат:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. (ASCII 72 ‘H’)
+++++++++++++++++++++++++++++. (ASCII 101 ‘e’)
+++++++.. (ASCII 108 ‘l’; выводим дважды)
+++. (ASCII 111 ‘o’)
-------------------------------------------------------------------------------. (ASCII 32 ‘ ’)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++. (ASCII 87 ‘W’)
++++++++++++++++++++++++. (ASCII 111 ‘o’)
+++. (ASCII 114 ‘r’)
------. (ASCII 110 ‘l’)
--------. (ASCII 100 ‘d’)
-------------------------------------------------------------------. (ASCII 33 ‘!’)
-----------------------. (ASCII 10 ‘\n’)

Можно удовлетвориться данным вариантом, однако, вспомним, что в языке существуют циклы, позволяющие сократить количество кода в однообразных операциях. Ниже приведен один из оптимизированных вариантов той же самой программы.

+++++ +++++             присвоить счетчику в ячейке #0 значение 10
[                           цикл для присвоения следующим четырем ячейкам значений 70/100/30/10
  > +++++ ++          добавить 7 к ячейке #1
  > +++++ +++++       добавить 10 к ячейке #2
  > +++               добавить 3 к ячейке #3
  > +                 добавить 1 к ячейке #4
  <<<< -              уменьшить на единицу счетчик в ячейке #0
> ++ .                 'H'
> + .                  'e'
+++++ ++ .             'l'
.                      'l'
+++ .                  'o'
> ++ .                 ' '
<< +++++ +++++ +++++ . 'W'
> .                    'o'
+++ .                  'r'
----- - .              'l'
----- --- .            'd'
> + .                  '!'
> .                    '\n'

Код отформатирован для удобства чтения и снабжен комментариями. При выполнении переносы и лишние символы будут проигнорированы. Итоговая программа представляет собой строку:
5.3  Описание программы Hello World

Разберем отформатированную команду построчно.
Первые 7 строк подготавливают память, присваивая соседним ячейкам значения, близкие к кодам символов выводимой фразы.
Присвоим ячейке #0 значение “10”, увеличивая ее на единицу 10 раз.
Начало цикла. Значение текущей ячейки - 10, поэтому содержимое цикла будет выполнено
Каждую итерацию цикла производится ряд действий над ячейками:
  #1 увеличивается на 7
  #2 увеличивается на 10
  #3 увеличивается на 3
  #4 увеличивается на 1
  #0 уменьшается на 1
Перед каждой итерацией мы возвращаемся в ячейку #0, значение которой последовательно изменяется с 10 до 0, поэтому цикл будет выполнен 10 раз
В результате в ячейках ##1-4 содержатся значения: 70, 100, 30, 10. Теперь нам потребуется гораздо меньше действий, чем в первом примере, для получения кодов символов “Hello World!”

5.4 Упражнения

1.     Измените пример с вводом-выводом так, чтобы переданные значения не перезаписывали предыдущие, а сохранялись в памяти
2.     Измените программу Hello World, чтобы вывести на экран ваше имя

Далее - Простые конструкции
Руководство по Brainfuck для новичков [3] (16.08.2014)
К началу

5 Первые программы на Brainfuck

5.1 Чтение и запись

Чтение символов с клавиатуры и вывод их на экран, пока не будет введено нулевое значение:
Результатом кода:
будет то же самое, однако, выход производится по коду 255. В некоторых средах исполнения невозможно передать на вход ASCII-код 000.

5.1.1 Описание

Программа состоит из пяти символов: , [ . , ]
Запятая считывает ASCII-код символа с клавиатуры.
Открывающая скобка является началом цикла While - если значение текущей ячейки больше нуля, выполняются команды внутри скобок. Если же введен ноль, программа продолжится за закрывающей скобкой и, поскольку, инструкций больше нет, завершится.
Точка выводит значение текущей ячейки на экран. Заметьте, что первый символ мы ввели за пределами цикла, иначе значение текущей ячейки было бы равно нулю и программа бы ничего не напечатала.
Снова запятая - ввод символа пользователем.
Закрывающая скобка завершает цикл While, перемещаемся к началу цикла.

Обратите внимание на порядок операций внутри цикла - мы сперва выводим значение, а затем считываем. Этим мы предотвращаем выход из цикла - текущая ячейка не должна быть пустой.

Далее - Hello World
Руководство по Brainfuck для новичков [2] (16.08.2014)
К началу

3 Основы языка: 8 команд Brainfuck

Язык состоит всего из восьми перечисленных ниже команд.
>  Сдвинуть указатель на одну ячейку вправо
<  Сдвинуть указатель на одну ячейку влево
+  Увеличить на единицу значение текущей ячейки
-  Уменьшить на единицу значение текущей ячейки
.  Отобразить ASCII-символ, соответствующий значению текущей ячейки на экран
,  Запросить ввод одного символа и сохранить его в текущей ячейке
[  Начало цикла while. Пока текущая ячейка не равна нулю, выполнять команды между скобками
]  Окончание цикла. Если текущая ячейка не равна нулю, вернуться к началу цикла
3.1 Программирование на Brainfuck

Программа на Brainfuck может представлять собой последовательность приведеных команд, перемешанных с любыми другими символами, игнорируемыми при компиляции. За исключением цикла [ ], команды выполняются последовательно, друг за другом. После выполнения последней команды программа завершается.

3.2 Упражнения

  1. Приведите примеры команд, аналогичных приведенным, в знакомых вам языках
  2. Изучите работу цикла [ ] применительно к различным значениям текущей ячейки памяти

4 Модель языка Brainfuck

Абстрактная машина, исполняющая Brainfuck содержит:
  программу с указателем текущей инструкции
  одномерный массив из 30000 однобайтных ячеек, заполненный нулями
  перемещаемый указатель данных, изначально находящийся в крайней левой ячейке
  потоки ввода-вывода, обычно соединенные с клавиатурой и монитором, и использующие кодировку ASCII.

В отличие от других небольших языков, память с данными отделена от памяти инструкций, и содержимое ячеек с данными не может оказать влияние на ячейки программы.

Далее - Первые программы на Brainfuck
Руководство по Brainfuck для новичков [1] (15.08.2014)
К началу

1 Введение

Представьте себе одномерную полосу с данными, например, магнитную ленту (классические машины Тьюринга работают с лентой) или компьютерную память. Для обозначения текущей ячейки используется указатель данных (магнитная головка). Каждая такая ячейка хранит один байт (значение от 0 до 255), слово (16 бит) или 24 бита данных. Автор предпочитает называть указатель курсором, однако, я своевольно оставлю его привычное название (прим. пер.)

Brainfuck - это минималистичный язык программирования, работающий с такой “лентой” в памяти, и состоящий лишь из восьми операндов. Несмотря на это он является Тьюринг-полным, что теоретически позволяет производить любые вычисления как, например, в языках Basic или C. Автор составил данное руководство из найденных им материалов по Brainfuck. Большинство текстов и кода позаимствовано у разных людей с указанием источников.

1.1.1 Авторские права

При цитировании были сохранены лицензии на распространение использованных текстов. Данный документ опубликован под лицензией GFDL.

2 Краткая история Brainfuck[wikipedia]

Исключая две команды ввода-вывода, Brainfuck является полным преемником языка P′′, созданного Коррадо Бомом  в 1964 году. Он также использовал шесть символов, эквивалентных соответствующим командам Brainfuck: +, -, <, >, [ и ]. Бом описал ряд программ, реализующих основные математические функции, поэтому, формально, первые программы на Brainfuck были написаны Бомом на бумаге в 1964 году, и уже тогда была доказана полнота языка по Тьюрингу.

Создавая Brainfuck в 1993 году Урбан Мюллер стремился разработать язык с компилятором как можно меньшего размера, вдохновившись таковым у FALSE - тот умещался в 1024 байта. На данный момент существуют компиляторы Brainfuck размером менее 200 байт.

Далее: Основы языка: 8 команд Brainfuck
Получить по клику слово из textarea (06.02.2014)
function caretPos(el)
  var pos = 0;
  // IE Support
  if (document.selection)
    el.focus ();
    var Sel = document.selection.createRange();
    var SelLength = document.selection.createRange().text.length;
    Sel.moveStart ('character', -el.value.length);
    pos = Sel.text.length - SelLength;
  // Firefox support
  else if (el.selectionStart || el.selectionStart == '0')
    pos = el.selectionStart; //нашли индекс кликнутого символа
  var str = el.value;
  var re = /(?!\d+)[\u00C0-\u1FFF\u2C00-\uD7FF\w]+/gi; //Это всего лишь аналог "\w+"
  while ((match = re.exec(str)) != null) {
    if (pos >= match.index && (pos <= match.index + match[0].length)) //если индекс в пределах слова

Вопрос на Google Answers
Поиск позиции в textarea
JavaScript, answers
Создать 100 папок по датам в Windows (05.02.2014)
На самом деле создастся менее 100 папок, т.к. часть итераций съедается в месяцы менее 31-дня, но уже в лом.

@echo off
setlocal EnableDelayedExpansion //иначе не работают приращения %-)
set /a d=%date:~0,2%
set /a m=%date:~3,2%
set /a y=%date:~6,4%

for /l %%x in (1, 1, 100) do (
  set /a d+=1

  if %d% gtr 31 (
    set d=1
    set /a m+=1
    if %m% gtr 12 (
      set m=1
      set /a y+=1
xcopy /d:!m!-!d!-!y! /l . .. >nul 2>&1 || goto loop //проверка корректной даты

mkdir "!d!.!m!.!y!"
copy file.txt "!d!.!m!.!y!/file.txt"

Вопрос на Google Answers
Необходимое курево
batch, answers
Проверенные дампы вендорских экзаменов (vce dumps) (29.01.2014)
Обновляемый список дампов, с которыми я ходил сдаваться.
  • 1Z0-878 Oracle Solaris 10 System Administrator Certified Professional Exam, Part II
  • 1Z0-880 Oracle Solaris 10 Network Administrator Certified Expert
  • 1Z0-821 Oracle Solaris 11 System Administration
    (Исправил кучу ошибок в дампе и сдал на 68%, совпадение с тестом ~ 50-60%)
  • ST0-148 Veritas Storage Foundation 6.0 for UNIX Technical Assessment
    (Совпадение с тестом ~ 70%, несколько ошибок, рекомендую все же прочитать гайд)
  • 250-273 Administration of Symantec NetBackup 7.6.1 and NetBackup Appliances 2.6.1 (pdf is for 250-371)
Зонинг на Brocade (24.01.2014)
Проверить видимость порта в зоне:
nodefind <wwn>
Имя текущей конфигурации:
switchshow | grep zoning
Создание зоны и добавление ее в конфигурацию:
zonecreate <zonename>, "<wwn>;<wwn/alias>"
zoneadd <cfgname>, <zonename>
Поиск по зонам:
zoneshow <wildcard>
Удаление участника зоны:
zoneremove <zonename>, "<wwn/alias>"
Исключение из конфигурации и удаление зоны:
cfgremove <cfgname> <zonename>
zonedelete <zonename>
Применение конфигурации после любых изменений:
cfgenable <cfgname>
Простая пагинация для таблички (05.04.2013)
$p=htmlspecialchars($_GET["p"], ENT_QUOTES);
if (!!$p) $start=$p*$num;
else $start=0;
$count = mysql_fetch_row(mysql_query("SELECT COUNT(*) FROM table"));
echo "Страница № ";
for ($i=0;$i<$count[0]/$num;$i++) {
  echo "<a href=/?p=".$i.">".$i."</a> / ";
$query = mysql_query("SELECT fields...
  FROM table
  LIMIT ".$start.",".$num
Задачка на собеседовании в techstudio.tv (23.03.2013)
"Имеется компания которая продает свой сервис. Сервис действует в течение 30 дней с момента оплаты, и отключается автоматически по истечению 30 дней. Если у Клиента работает сервис, Клиент считается действующим, если сервис не работает, Клиент считается не действующим. При каждой оплате, автоматически, в базу данных заносится НОВАЯ строчка, которая включает в себя, ФИО Клиента и дату. Предложите алгоритм (последовательность действий) как используя базу данных найти всех не действующих Клиентов."
SELECT name, MAX(date)
FROM test_table
Флуд о поиске в Joomla (28.11.2012)
Компонент поиска (com_search) в данной CMS - далеко не то, чем кажется на первый взгляд - он эксплуатирует чужой труд и кидает сам себе запросы, да еще и преобразуя методы на ходу.
Рабочей лошадкой при поиске является плагин (search), а компонент занимается приемом и обработкой пользовательских данных и выводом результата. Кстати, в запасе Joomla еще имеется модуль поиска и, так называемый, "умный поиск", при включении которого база растет неимоверными темпами.
С пересылкой запросов все настолько же путано: поисковая форма POST'ом отправляет данные контроллеру компонента поиска, который GET'ом пересылает их модели, которая передает их вызываемой из плагина функции.
Произвольное независимое поле материала в Joomla (28.11.2012)
На этот раз добавим полноценное поле в базу и во все соответствующие инстанции, будто так оно и было. Для примера будем ковырять имеющийся тип материала - статью.
Содержимое материалов хранится в таблице 'content'. При установке Joomla по умолчанию предлагает задать для своих таблиц префикс, поэтому следует поискать таблицу вида 'xxxxx_content'. Добавим в нее поле города:
Опишем необходимое поле в модели формы редактирования (/administrator/components/com_content/models/forms/article.xml). Поместим его внутрь основного набора полей (fieldset), располагающегося в основной части окна редактирования материала.
  <fieldset addfieldpath="/administrator/components/com_categories/models/fields" >
    <field name="city" type="text" label="Город"
      description="Город" class="inputbox" size="45" />
//Использование произвольных значений и, особенно, кириллицы в полях 'label' и 'description' иначе как вкорячиванием не назовешь, т.к. лучше указывать здесь понятные константы заглавными буквами, которые парсятся и заменяются значениями для текущего языка из файлов в каталоге /language/.
Теперь, чтобы увидеть поле в административной панели, добавим его в шаблон редактирования материала (/administrator/components/com_content/views/article/tmpl/edit.php):
  <fieldset class="adminform">
    <li><?php echo $this->form->getLabel('city'); ?>
    <?php echo $this->form->getInput('city'); ?></li>
Можно прямо сейчас бежать в админку и заполнять данное поле у всех материалов. Потом бежать в базу и видеть, что значения и в самом деле записываются. Но Joomla пока так не думает.
Запрос в базу для выборки полей материала производится в его модели (/components/com_content/models/article.php). Для добавления нашего поля требуется отредактировать запрос следующим образом:
//Префикс '.a' возникает оттого, что далее в запросе таблице 'content' назначается данный псевдоним: '$query->from('#__content AS a');'.
Теперь можно смело выводить созданное поле в шаблоне материала (/conponents/com_content/views/article/tmpl/default.php), например, перед основным текстом:
  <?php echo $this->item->city; ?>
  <?php echo $this->item->text; ?>

Если хочется отделаться меньшей кровью
Типы полей формы в Joomla
Пагинация (20.10.2012)
Когда постов становится много, нужна разбивка по страницам.
Получаем номер страницы в GET:

  isset($_GET[page]) ? $page=$_GET[page] : $page=0;
Считаем количество строк (в моем случае - просто вся таблица):

  $row=mysql_fetch_row(mysql_query("SELECT count(*) FROM Table"));
  $count = $row[0];

Количество постов на страницу и вычисления границ выборки:

  $posts_per_page = 5;
  $page_start = $page*$posts_per_page;

В конец mysql-запроса добавить:

  LIMIT $page_start,$posts_per_page

Вывод ссылок next-prev:

  if (($page+1)*5<$count) {?>
    <a href="/page<?=$page+1?>/">Prev page</a>
  if ($page>0) {?>
    <a style="float: right;" href="/page<?=$page-1?>/">Next page</a>
Задание симферопольского Яндекса (20.10.2012)
Пропарсить "односвязный список в обратном порядке".
Самому было тяжело въехать, почему же оно так работает, но все же mission complete :).

function reversePrint (linkedList) {
  if (linkedList.next) reversePrint(linkedList.next);

var someList = {
    value: 1,
    next: {
        value: 2,
        next: {
            value: 3,
            next: {
                value: 4,
                next: null
reversePrint(someList); //4 3 2 1

Небольшой апдейт - раз имеется next, то хочется иметь и prev со ссылкой на родителя. Легким движением руки модифицируем функцию.

function reversePrint (linkedList) {
  if (linkedList.next) {
    linkedList.next.prev = linkedList;
  if (!linkedList.prev) console.log(linkedList);

Выдаст в консоль она самый старший элемент (у которого нет родителя) а в дереве появятся обратные ссылки.
Линк на задачу
Модель Солнечной системы (19.10.2012)
Точнее - модель планет земной группы с предельно упрощенными характеристиками - соотношение размеров планет и средних радиусов их орбит примерно соблюдено, в остальном же царит великий рандом. Все элементы являются объектами одного единственного конструктора.

Start  Hide names
JavaScript, Canvas
И снова про футер (18.10.2012)
Если вам надоело изобретать очередной замысловатый способ размещения контента и стили к нему для того, чтобы пресловутый подвал сайта отображался в отведенном для него месте, возможно, стоит обратиться к динамическому изменению его положения.
Данный способ предполагает смещение подвала вниз на разницу в высоте "экрана" и контента. В качестве "экрана" будет выступать высота тега body, а контент определим по высоте блока, обернутого вокруг всех элементов страницы (в том числе и подвала). Надо сказать, что везде, кроме хрома, внешний блок не требуется, т.к. высоту содержимого можно брать из величины offsetHeight тега body, но что поделаешь.
  //var contentHeight = document.body.offsetHeight;
  var contentHeight = document.getElementById('content').offsetHeight;
  var bodyHeight = document.body.scrollHeight;
  if (contentHeight<bodyHeight) document.getElementById('footer').style.marginTop = bodyHeight-contentHeight;
PHP-авторизация (18.10.2012)
Какой же сайт может существовать без супер-секретной авторизации. Для местных нужд я написал следующую функцию. Для многопользовательского режима $login и $password будут итерироваться исходя из количества строк в таблице базы с пользователями, разумеется. Ну и вместо пароля во всех случаях желательно использовать хеш.

function auth() {
  if (isset($_POST[logout])) {
    $output = "Bye";
  if (isset($_SESSION[login])) {
    $output = $_SESSION[login].'
    <form class="login" method="POST">
      <input type="hidden" name="logout" value="'.$_SESSION[login].'">
      <input type="submit" value="Выход">
  else {
    if (isset($_POST[login])) {
      if ($_POST[login]!=$login) {
        $output = "No such user";
      else if ($_POST[password]!=$password) {
          $output = "Wrong password";
      else {
        $_SESSION[login] = $_POST[login];
        $output = auth();
    else {
      $output = '
      <form class="login" method="POST">
      <input type="text" name="login">
      <input type="password" name="password">
      <input type="submit" value="Вход">
    return $output;

Перед выводом контента я делаю $output = auth(), далее выводим $output в нужном месте. Проверка на "хорошего парня" определяется существованием $_SESSION[login]:
if (isset($_SESSION[login])) echo 'Top secret';
Стрелочные часы (21.10.2012)
Для моделирования вращательного движения по окружности необходимо рассчитать лежащие на ней проходимые точки, при этом плавность хода, т.е. количество таких точек, определяется углом поворота за шаг. Координаты каждой точки определяются тригонометрическими функциями угла между проходящим через нее радиусом и положительным направлением оси абсцисс: синус равен координате по Y, косинус - по X.
Первый пришедший в голову вкусный и полезный пример использования всего этого добра - разместить на canvas'е стрелочные часы.
Для начала необходимо получить текущие значения для каждой стрелки и выразить их в углах.
  var date = new Date();
  var a = [Math.PI/30*date.getHours()*5, Math.PI/30*date.getMinutes(), Math.PI/30*date.getSeconds()];
Если использовать синусы и косинусы данных углов для рисования стрелок, то выйдет, что сутки начинаются в 3 часа, а сами часы идут задом наперед. Чтобы этого избежать, необходимо поменять местами X и Y, и изменить знак у Y.
На холсте стрелки будем рисовать методом lineTo:
  for (var i in a) {
    context340.moveTo(150,150); //центр
    n = parseInt(i)+1; //длина стрелки
    context340.lineWidth=2/n; //толщина
JavaScript, Canvas
Три метода перемещения объекта на плоскости (15.10.2012)
Перенеся свои опыты по разработке двигательных поведенческих примитивов бегающих квадратиков на canvas, я наконец, чувствую, насколько просто и удобно, вкупе с объектным подходом, здесь все делать.
Первичное действие в анимации - движение предмета по прямой к установленной точке и я рассмотрю три способа это реализовать.
Первый способ я бы назвал "шашечками" - это передвижение по восьми возможным направлениям, где дистанция до цели определяется длиной наибольшей проекции на одну из осей координат. Способ предельно прост и каждый шаг четко укладывается в единицы системы координат, однако, не очень естественно выглядит предмет, нарезающий крутые углы по пути к цели.
Функции писались, как внутренние модификаторы объекта, поэтому this - это движущийся объект, а target - координаты цели. Переменная speed просто хранит количество единиц измерения на один шаг.

      if (this.x<target.x) this.x+=this.speed;
      if (this.x>target.x) this.x-=this.speed;
      if (this.y<target.y) this.y+=this.speed;
      if (this.y>target.y) this.y-=this.speed;

Следующий способ - тригонометрическое уравнение прямой. Путевая линия, конечно, строится, однако, функциональная зависимость вертикальной координаты от горизонтальной делает движение неравномерным в различных участках координатной плоскости и при часто выпадающих обстоятельствах, объект никогда не совместится с целевой точкой.

      var k = (target.y - this.y)/(target.x - this.x);
      var b = (target.x*this.y - this.x*target.y)/(target.x - this.x);
      if (this.x<target.x) this.x+=this.speed;
      else this.x-=this.speed;
      this.y = k*this.x+b;

Третий способ - движение по диагонали воображаемого прямоугольника, соединяющей объект и точку. Диагональ - или гипотенуза прямоугольного треугольника определяется по всем известной формуле. Далее представим на данной линии меньший прямоугольник, с диагональю, равной желаемой длине шага. По теореме подобия треугольников определим величины координат x и y.

      var distance = Math.round(Math.sqrt(Math.pow(Math.abs(this.x-target.x),2) + Math.pow(Math.abs(this.y-target.y),2)));

На данный момент я остановился на последнем варианте, как наиболее "прямом" и логичном. Примеры применения этих способов представлены ниже.

JavaScript, Canvas
Заведение однотипных пользователей unix (15.09.2012)
Случай индивидуальный, зато тренировка shell-скриптинга.

if [ "$#" -lt 6 ];
  echo "Usage: $0 baseName startNum endNum gid GID hash"
  exit 0
for i in $(eval echo {$2..$3})
    useradd -g $4 -G $5 -d /export/home/$1$i -m -s /bin/ksh $1$i
    sed -e 's/'${1}${i}':\*LK\*/'${1}${i}':'${6}'/g' /etc/shadow > /etc/shadow.old
    mv /etc/shadow.old /etc/shadow

P.s.: солярис не позволяет указывать хеш пароля в useradd
Произвольное поле для материала в Joomla (20.08.2012)
Фишка Джерси - добавить произвольное поле к материалу без работы с БД:
Заносим данные поля в /administrator/components/com_content/models/forms/article.xml

<fields name="images">
    description="COM_CONTENT_FIELD_INTRO_DESC" />

В компоненте выуживаем данные:
<?php foreach ($this->items as $i => $article) : ?>
<img src="<?=json_decode($article->images)->image_intro?>"/>
<?php endforeach; ?>

Это возможно, т.к. содержимое каждой предопределенной группы полей (fields) хранится в json.
Альтернативные шаблоны Joomla (20.08.2012)
Изменение отображения компонентов:
в /templates/%templateName%/html/%com_name%/%viewName%/ кладутся php файлы из /components/%com_Name%/views/%viewName%/tmpl/
Добавление шаблона для пункта меню:
там же подредактировать %templateName%.xml
Шаблоны модулей кладутся прямо в корень:
Софт и пример для PIC18 (29.02.2012)
Proteus - http://rutracker.org/forum/viewtopic.php?t=3958483
mikroC - http://eldigi.ru/site/programms/mikroC.rar
Мигаем светодиодом:
void main() {
JavaScript (13)
PHP (11)
Brainfuck (8)
adm (8)
Joomla (4)
Canvas (3)
answers (2)
API (2)
CMS (2)
Modx (2)
jQuery (1)
Ajax (1)
SQL (1)
Shell (1)
batch (1)