Просьба оставить комментарий





Если вам понравился или не понравился топик. Я что то забыл или не дописал, то вы можете оставить свой комментарий и я постараюсь исправить это в ближайшее время.

пятница, 2 ноября 2012 г.

Решение проблемы: При запуске игр и полноэкранных приложений виснет Outpost и само приложение

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

Причем ладо бы он просто спрашивал разрешить или нет запуск, а то происходит запуск, приложение блокируется, при нажатии на Alt+ctrl+delete выскакивает и сразу же пропадает окошко с возможностью выбора действий, а приложение так и висит.

Решил просто отключить его вообще, хоть и  опасно. У моего лицензионного оутпоста pro версии это делается во вкладке "Общие". Называется эта опция "Обнаруживать попытки запуска полноэкранных приложений (Игровой режим)". Просто снимаем галку и все начинает работать.

Надеюсь подобную проблему в оутпост скоро решат, так как функция полезная, а деньги уплачены. :)

среда, 17 октября 2012 г.

SphinxSearch Несколько индексов таблиц и баз данных на одном сервере

SphinxSearch Долго не мог понять как организовать подобную фишку на одном серваке, так как в скрипте api к php нельзя явно указать в какой таблице нужно производить поиск. На сайтах в гугле нашел какие то костыли с использованием дополнительного параметра или я просто искал. Опишу мое решение вдруг пригодится.

Проблему решил так, так как процессов searchd можно запустить несколько, то их можно просто повесить на разные порты в стандартном конфиге используется порт 9312, то есть для 1 индекса его можно спокойно использовать, а вот для второго индекса просто делаем конфиг с портом 9313 например и самое важное, что строку с listen = localhost(127.0.0.1) нужно закомментировать иначе выдаст следующую ошибку:

bind() failed on 127.0.0.1, retrying.

Когда у нас будет 2 конфига, можно использовать также разные пути к pid, log и базам, я просто во втором конфиге добавил "-2". Собственно это все что требуется. После получения 2х конфигов делаем индексацию и запускаем 2 демона searchd с разными конфигами.

В Google Webmaster появилось долгожданное нововведение. Отклонение ссылок

Многочисленные просьбы от владельцев сайтов привели наконец то к появлению этой полезной функции в вебмастере. Изначально эта функция появилась вэбмастере поисковой системы bing от майкрософт. Основная фишка этой функции избавиться от негативного влияния плохих ссылок на поисковую выдачу, которые могут размещаться конкурентами сайтов. Пока это функция довольно сложно реализована, для того чтобы отказаться от ссылок и сайтов нужно составлять список в текстовом файла, а потом загрузить его в панель вэбмастера по этому адресу https://www.google.com/webmasters/tools/disavow-links-main

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

На серче дают такие рекомендации:
Вкратце руководство для тех кто не понял о чем написано:
- заходим в https://www.google.com/webmasters/to...vow-links-main
- выбираем свой сайт
- загружаем .txt файл с ссылками на страницы котрые вы считаете размещают на вас спам (каждая ссылка с новой строки, можно запретить как домен так и отдельную страницу, так же можно оставить комментарий вставив символ # в начале строки)
- далее загружаем и ждем переиндексации с учетом запретов (написали что ждать несколько недель)
- далее подаем сайт на пересмотр - https://www.google.com/webmasters/to...deration?hl=ru

понедельник, 24 сентября 2012 г.

Список проверенных партнерских программ в рунете.

Контекстная реклама


Google Adsense - самый доходный и простой способ заработка. После регистрации сразу же можно размещать рекламные блоки и реклама начнет крутится у вас на сайте. Из минусов сложная процедура получения денежный средств. В России получение возможно в данный момент через систему рапида, на почту, вебмани, на карту банка. Для получения необходимо подтвердить адрес. Делается это бумажным письмом. Идет 2-3 недели из ирландии.
Так же очень высокий уровень блокировок аккаунтов за нарушение правил, причем поддержка работает отвратительно. вообще не работает можно сказать.

Yandex. Рекламная сеть. Второй по популярности и доходности источник получения прибыли.
Из минусов высокие требования к площадкам, варез не примут. Адалт само собой тоже.
Для работы можно заключить договор с Яндексом или же работать через посредников.
Получение очень простое. Поддерживает большое количество платежных систем. Очень надежный партнер mixmarket.biz Регистрация партнера, который является официальным партнерем + отчисляет издателям столько же сколько и яндекс.

Тизеры


DirectAdvert надежная тизер партнерка. Проблемы бывают с выплатами, но редко и все выплачивают, просто бывает задерживают.

TeaserNet Есть настройка фильтров. Очень желательно ее настроить чтобы на нарваться на порно.

Баннеры


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

Файлообменники

DepositFiles довольно старый партнер. Платит за скачивание ваших файлов с серверов DepositFiles. Выплаты производить скачивания вроде корректно считает.

Твиттерстоки

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

четверг, 6 сентября 2012 г.

Установка VMware Tools на Debian 6

Для начала установим необходимые библиотеки для текущей версии:

# apt-get install make gcc linux-headers-$(uname -r)

Для начала надо отмонтировать текущий диск в виртуальном CDrom если он там есть:

umount /media/cdrom

Далее в низу экрана виртуалки должен быть всплывающий топки об установке VMware Tools
Если такого нет, можно нажать правой кнопкой мыши на виртуалке в списке виртуалок и нажать на пункт Install VMwate Tools.

Далее:
Монтируем диск
# mount /media/cdrom
Переходим в папку tmp
# cd /tmp
Распаковываем в tmp архив с тулзами
# tar xfz  /media/cdrom/VMwareTools*.tar.gz

Важно: Если по какой то причине не находит архив, возможно что у вас примонтирован не правильный диск, если это так и там стоит например образ дистрибутива Debian, то надо сменить его на образ linux из папки VMWare в Program Files(пр. у меня: C:\Program Files (x86)\VMware\VMware Workstation\linux.iso).

Когда распаковка завершиться начинаем установку:
# cd vmware-tools-distrib
# ./vmware-install.pl

Все. На большинство вопросов, которые возникнут при установке, можно ответить рекомендуемым методом.

вторник, 4 сентября 2012 г.

Закрываем доступ к директории сайта с доступом по определенным ip адресам

Наконец то дошли руки сделать себе статический ip домой. На работе и так был статический и появилась возможность пожестче защитить свой вэбсервер от взлома через возможные баги в скриптах. А так же перебора например в phpmyadmin

Задача состоит в ограничении доступа к подкаталогам сайта по http по определенным ip адресам. Для этого создадим .htaccess файл в папке, к которой надо ограничить доступ.

order deny,allow
deny from all
allow from ip_address_1
allow from ip_address_2

Все, осталось только убедится в его работоспособности.
Если вдруг это правило не заработало то скорее всего в файле который описывает конфигурацию сайта в папке site-available в теге где указана рутовая директория для вашего сайта не указана дополнительная опция.

    <Directory '/var/www/site/'>
        AllowOverride All
    </Directory>

Для phpmyadmin AllowOverride изначально выставлен в none

пятница, 31 августа 2012 г.

nginx+phpMyAdmin ошибка: Время ожидания соединения истекло

После настройки nginx как фронтенд для Apache 2.2 столкнулся с ошибкой: Время ожидания соединения истекло. При этом в урле явно задавался порт 81, при ручной смене на 80 порт сразу все вставало на места и можно было работать с phpmyadmin, правда отсутствовали картинки(nginx не пахал), но по завершении сессии проблема возникала снова.

Единственный вариант которым удалось решить проблему создать поддомен pms.domain.com и в пути к директории с phpmyadmin указать путь со скриптом

Добавляем в site-available конфиг для поддомена в Апач и nginx

Для Apache2:

<virtualhost *:81>
ServerAdmin webmaster@localhost

DocumentRoot /usr/share/phpmyadmin
ServerName pms.domain.com
ServerAlias www.pms.domain.com

<directory /usr/share/phpmyadmin>
Options +FollowSymLinks
AllowOverride None
order allow,deny
allow from all
</directory>

ErrorLog /var/log/apache2/phpmyadmin_error.log
CustomLog /var/log/apache2/phpmyadmin_access.log combined
ServerSignature On
</virtualhost>

Для nginx:

server {
        listen   80;
        server_name pms.domain.com;

        access_log  /var/log/phpmyadmin-access.log;

        location / {
                proxy_pass         http://127.0.0.1:81/; # делаем переадресацию запросов на apache
                proxy_redirect     off;

                proxy_set_header   Host             $host;
                # Эти настройки необходимы, что бы из скриптов было видно реальные IP пользователя, а не фронт-части
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

                client_max_body_size       10m;
                client_body_buffer_size    128k;

                proxy_connect_timeout      90;
                proxy_send_timeout         90;
                proxy_read_timeout         90;

                proxy_buffer_size          4k;
                proxy_buffers              4 32k;
                proxy_busy_buffers_size    64k;
                proxy_temp_file_write_size 64k;
        }
}






Добавляем через a2ensite, делаем symlink для nginx и рестартим

среда, 29 августа 2012 г.

Решение проблемы возврата средств, незаконно списанных со счета мобильного оператора МТС

Собственно как все началось

Месяц назад установил приложение с Android Market. В комментариях заметил надпись, что есть подозрение на вирус, но внимания не обратил, так как были положительные отзывы. В итоге начали приходить уведомления о том что нужно "обновить скайп". Для этого было предложено перейти по ссылке. После перехода ссылки на устройство установился тройан и интенсивно начал отправлять смс на платные номера. + осуществил подписку на платный номер ~17р в день. В итоге за 2 месяца я попал на ~700р. Так как кроме интернета и пары звонков в день я услугами оператора больше не пользуюсь, попал я хорошо и собственно во время заметил пропажу.

Вирус который отправлял смс я удалил в первый же день с помощью Norton антивируса для Андроид платформы, а вот подписку я не заметил. В начале августа пополнил счет на 500р. и удивился когда 19 числа мне пришла смс с уведомлением об окончании средств на счете.

Что делал

Сначала я позвонил в поддержку сотового оператора. Выяснять на каком основании у меня списывают ежедневно. Оказалось что я подписан на какой то платный контент стоимостью 17р в день.На вопрос: "На каком основании мне предоставляется услуга которая мне не требуется?". Мне ответили: "Большинству пользователей она требуется и они подключают без уведомления?".

На сайте оператора нашел электронный ящик на который надо отправлять информацию о подобных случаях. Убедился что эта функция у них не работает в принципе.

Что советую сделать для быстрого решения вопроса

Добиваться чего то по телефону и по email бесполезно сразу надо топать в салон.

Для быстрого решения вопроса по шагам:
1.Получить отчет о списании:
а. Заказать подробную выписку в формате PDF в личном кабинете на сайте МТС за нужные периоды.
б. Если нет времени регистрироваться или это сделать сложно для вас. Тогда придется сходить для начала в салон МТС и заказать распечатку детализации за нужные вам периоды. Делают их не быстро, мне сообщили, что около 4 часов.
2. Когда вы получите выписку очень рекомендуется позвонить по телефону 8 800 250 0890 и спросить где в вашем городе можно написать претензию о возврате средств(Так как салон может работать по франшизе и не факт, что примут, лично у меня такой проблемы не было, но в интернете прочитал про такие случаи). Меня направили в ближайший салон МТС.
3. Перепишите все короткие номера(идентификаторы) через которые списывали средства. Они могут быть не только цифровые, но и буквенные. У меня было 2 номера(идентификатора):
Dostup_k_011_039 - подписка 17р/д
Kontent_po_karmanu_3855 - в один день списал 145 р.
4. Попросите бланк о претензии, там его дают установленной формы.
5. Напишите претензию вида:
"Прошу вернуть денежные средства списанные за услуги которыми я не пользовался." Далее перечисляем идентификаторы с датами списаний. В моем случае было так
Подписка "28.07-19.08 Dostup_k_011_039 сумма"
Платные смс "28.07 время сумма Kontent_po_karmanu_385"
Все. Ставим подписи, проверяем, что работник салона тоже везде подписался.

Что вышло в итоге

По информации работника салона претензию рассматривают по закону 30 дней, обычно 10 дней, в моем случае через 2 дня вернули деньги.
Деньги вернули не все. Претензию составлял на сумму 600 рубле вернули менее 500 рублей.

Что можно сделать еще

1. Позвонить по телефону 8 800 250 0890 и наехать на оператора. Конечно же оператор тут ни в чем не виноват особо, но чем больше на них будут наездов, тем быстрее МТС разберется с этой проблемой, так как народ из поддержки просто начнет убегать.
2. Потребовать отключить все подписки на платный контент и вообще заблокировать эту функцию по тому же телефону.
3. Установить антивирус, если у вас еще не установлен. Для андроида Dr WEB и Norton.

PS: Если есть какие, то вопросы пишите в комментарии попробую ответить и дополнить статью

среда, 15 августа 2012 г.

Ошибка kb927917 при использовании recaptcha

Трабла возникала в осле восьмой версии IE8 из за этого не выводилась рекламка и вообще не отображалась страница, обнаружилось спустя год после использования :( Использовался код php для отображения рекаптчи.


echo recaptcha_get_html($publickey);
Вот из за этой гадости проблема и возникла Сама ошибка kb927917 является результатом того, что яваскрипт пытается получить доступ к элементу который еще не отображен. Возникает по целому ряду случаев. В рекаптче проблема именно в этой строке:


echo recaptcha_get_html($publickey);


Гуглер вообще результатов мало дал, еле нарыл информацию по этому вопросу. Решением является использование яваскрипта вместо кода php!

Тоесть комментируем эту строку
//echo recaptcha_get_html($publickey); и пишем под ней

echo "<script type=\"text/javascript\"
src=\"http://api.recaptcha.net/js/recaptcha_ajax.js\"></script>
    <script>
    window.onload = function () {
    Recaptcha.create(\"";
    echo $publickey;
    echo "\",
    \"recaptcha_div\", {
     theme: \"red\",
     callback: Recaptcha.focus_response_field
    });
    }
                                       
    </script>

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

воскресенье, 15 июля 2012 г.

Ошибка 413: Request Entity Too Large

Ошибка возникает если вы пытаетесь загрузить на сервер файл php скриптом. Это ограничение в версии Apache 2.2 устанавливается в файле apache2.conf параметром secrequestbodylimit значение устанавливается в байтах. Установите максимальный размер для аплоада.

воскресенье, 8 июля 2012 г.

Копирование элементов из одной базы данных в другую с похожими строками

INSERT INTO `db`.`table_to`
SELECT *
FROM `db`.`table_from` ;
Если необходимо скопировать только некоторые столбцы, то применяем следующую конструкцию:
INSERT INTO `db`.`table_to` (`t1_2`, `t2_2`, `t3_2`, `t4_2`)
SELECT `t1`, `t2`, `t3`, `t4`
FROM `db`.`table_from` ;
Для копирования данных из одной таблицы MySQL в другую по условию, можно использовать следующий запрос:

INSERT INTO `db`.`table_to` (`t1_2`, `t2_2`, `t3_2`, `t4_2`)
SELECT `t1`, `t2`, `t3`, `t4`
FROM `db`.`table_from`
WHERE  `t2` < '2010-07-01 11:37:38';

вторник, 3 июля 2012 г.

Интересное письмо от hetzner.de

During the night of 30.06.2012 to 01.07.2012 our internal
monitoring systems registered an increase in the level of
IT power usage by approximately one megawatt.

The reason for this huge surge is the additional switched
leap second which can lead to permanent CPU load on Linux
servers.

According to heise.de
, various Linux distributions are
affected by this. Further information can be found at:
http://www.h-online.com/open/news/item/Leap-second-Linux-can-freeze-1629805.html

In order to reduce CPU load to a normal level again, a
restart of the whole system is necessary in many cases.
First, a soft reboot via the command line should be
attempted. Failing that, you have the option of performing
a hardware reset via the Robot administration interface.
For this, select menu item "Server" and the "Reset" tab
for the respective server in the administration interface.

Please do not hesitate to contact us, should you have any
queries.



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

Некоторые версии Линукс систем могли не выдержать такой нагрузки и даже зависнуть. И причем перезагрузить можно было только через аппаратную перезагрузку роботом.

понедельник, 25 июня 2012 г.

Набор админского софта под Windows

Здесь я перечислю набор софта который помогает в админской работе на рабочих станциях пользователя.

Your Uninstaller Pro позволяет деинсталлировать программу даже если не возможно это сделать через установку и удаление программ. После удаления происходит проверка на наличие ключей в реестре которые остались после удаления, помогая таким образом полностью очистить систему. Часто подобные программы игнорировал, но один раз помогло в удалении ПО МФУ, так как стандартными методами никак не хотел удаляться.

Unlocker - программа позволяющая удалить любой файл даже когда он заблокирован от удаления, например вирусом или системой.

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

Putty - известный клиент для SSH и других протоколов. Всегда бесплатный, всегда опенсурс, но есть проблемы в сохранении настроек, скорее всего все данные о подключениях хранятся в реестре и приходится сохранять настройки сессий заново.

TeamViewerQS - очень удобная программа, аналог удаленного помощника Windows при запуске выдаст 2 строки которые надо отправить удаленному пользователю, а удаленному пользователю надо их забить при создании соединения, и т.о. происходит перехват управления компьютером.

Ошибка: Access denied for user 'root'@'localhost' (using password: YES)

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

1. Залогиньтесь как пользователь root на машину с запущенным MySQL сервером.
2. Остановите MySQL server используя следующую команду.
#/etc/init.d/mysql stop
3. Теперь нам нужно запустить MySQL без пароля
# mysqld_safe --skip-grant-tables &
4. Подключитесь к MySQL серверу используя mysql клиент
# mysql -u root
5. Вы увидите консоль mysql
mysql>
6. Устанавливаем новый пароль пользвателя root:
mysql> use mysql;
mysql> update user set password=PASSWORD(”newpassword”) where user=’root’;
mysql> flush privileges;
mysql> quit




Замените newpassword на новый требуемый вам пароль root. Команда flush privileges необходима для того чтобы изменения вступили в силу немедленно.
Опять останавливаем MySQL
# /etc/init.d/mysql stop
Протестируем новый пароль. Для начала запустим MySQL в нормальном режиме
# /etc/init.d/mysql start
# mysql -u root -p
Ввводим пароль root и проверяем

Определение размера каталога(директории, папки) в Linux

du /home
покажет в килобайтах размер /home и всех её поддиретокрий
du -h /home
покажет это в килобайтах и мегабайтах, так же выведет список с размером всех поддиректорий
du -sh /home
покажет только общий размер диретории, без листинга поддиректорий.

понедельник, 30 апреля 2012 г.

Поиск дублей в базе данных. Очень быстрый способ

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

select Поле_для_проверки_на_дубль, count(*) from имя_базы group by Поле_для_проверки_на_дубль having count(*) > 1;

Этот способ работает очень быстро, 11000 записей переваривает за пару секунд и нашел 320 дублей.

После этого осталось только выполнить запрос скриптом и удалить

$result = mysql_query("select Поле_для_проверки_на_дубль, count(*) from имя_базы group by Поле_для_проверки_на_дубль having count(*) > 1;");

while ($row = mysql_fetch_assoc($result))
{
    echo "Есть дубль ".$row['id']." - ".$row['Поле_для_проверки_на_дубль']."<br/>";
    $result2 = mysql_query("DELETE FROM имя_базы WHERE id='".$row['id']."';");
}


Еще один способ

SELECT *
FROM `items`
WHERE CONCAT( `items`.`brandid` , `items`.`model` )
IN (


SELECT CONCAT( `items`.`brandid` , `items`.`model` ) AS x
FROM `items`
GROUP BY x
HAVING COUNT( x ) >1
)
 

пятница, 27 апреля 2012 г.

Как не навредить сайту при проведении технических работ

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


<?php
header('HTTP/1.0 503 Service Unavailable'); header('Retry-After: '.(14*60*60)); // заходите через 14 часов
?> 

Эта операция позволяет не потерять проиндексированные страницы. 

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

четверг, 12 апреля 2012 г.

Samsung Galaxy Note N7000: Первые впечатления

Девайс супер!

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

Фотокамера меня порадовала, сравнивать правда было особо не с чем, до этого был HTC Touch Diamond 2  c 5-ю мегапикселами. Сколько тут реальных не знаю, но написано 8. Главное отличие, что есть встроенная вспышка. Автовспышка работает очень качественно и корректно для меня. Хотя я не фотограф мне судить сложно.

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

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

GPS ловит быстро, буквально за 10 секунд можно начать прокладывать маршрут после включения.

Софт весь есть. Нашел все аналоги программ от Windows Mobile и все бесплатные. Выводы делать рано, но при тестовых проверках весь софт с со всем справлялся. И главное очень все между собой интегрируется, что очень радует.
http://mcgrp.ru/smartfonyi-i-kommunikatoryi-SAMSUNG-Galaxy-Note.html

понедельник, 9 апреля 2012 г.

Samsung Galaxy Note N7000: Софт маст хайв

AdSense Dashboard отображает статистику заработка в системе Google Adsense. Имеет удобный интерфейс где отображается доход на сегодняшний и вчерашний день, а также за месяц и с начала работы в системе. Обновление происходит автоматически раз в полчаса.

DailyRoads Voyager делает из телефона видеорегистратор. По отзывам самый лучший из бесплатных и многих платных решений.

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

ES Проводник проводник для работы с файловой системой. При получении root прав становится вообще незаменимой вещью для установки не официального софта и патчей.

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

KeePassDroid версия хранилища паролей для андройда. Синхронизируется через dropbox как всегда 10 из 10.

Ping & DNS софт для админов. Вполне выполняет свою функцию. Доволен.

ConnectBot опять же для админов. Клиент для ssh и telnet Пока не юзал, но отзывы очень хорошие. Есть проблемы с кодировкой в telnet

Remember The Milk задачи. Единственное что не хватает в evernote и сервисах гугла. Лично для меня удобнее, чем календарь с напоминалками.

Будильник Xtreme очень простая и удобная настройка. 10 из 10

Мемиана сервис для синхронизации контактов из большинства систем коммуникаций. Ищет дубли и позволяет их корректно объединить.

Телефонный Шпион программа для записи телефонных переговоров. Не требует root прав для корректной записи и установки дополнительных патчей.  При стандартных настройках собеседника слышно плохо, но если в установках задать автоматический уровень громкости, то пишет отлично.

Яндекс.Навигатор порадовала программа. Яндекс всегда меня радовал своими сервисами. Многие его сервисы намного удобнее, чем у основного конкурента.

Skype  клиент для всем известного сервиса ip телефонии. После установке при звонке какому либо контакту отображается меню с выбором типа звонка. Обычный телефон или через Skype клиент.

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

Barcode Scanner программа для распознавания qr кодов, работает шустро. Почему нет встроенной программы в самом андроиде - загадка.

GTask менеджер задач, рекомендуют пользователи + происходит синхронизация с google. Есть частичная русификация, будем надеяться на полную.

Все эти приложения ставятся через сервис Google Play и отлично без тормозов и глюков(по крайней мере не замечено) на устройстве Samsung Galaxy Note N7000
http://mcgrp.ru/smartfonyi-i-kommunikatoryi-SAMSUNG-Galaxy-Note.html

четверг, 5 апреля 2012 г.

Ошибка: failed with exit status 255


Эта ошибка возникает из за указания относительного пути в исполняемом файле php скрипта при запуске его по cron. То есть внутри указан путь в виде "../config/func.conf.php", а для исполнения нужно указать полный путь /var/www/site/config/func.conf.php .

Также если вдруг не происходит исполнения скрипта, то нужно проверить указан ли полный путь к интерпретатору php и выставленны ли правильные права на скрипт.

понедельник, 2 апреля 2012 г.

Ошибка: bad protocol version identification

Полез я однажды на сервер по ssh через putty и получил вместо запроса логина полную версию своего ssh сервера. После нажатия кнопки Enter просто завершалась сессия. Первая мысль появилась, что сервак наконец то хакнули, залез на сайт, но сайт работал. Так как доступа по ssh не было пришлось лезть через клиента vsphere мониторить виртуалку.

Перезапуск сервера проблему не решил. Полез смотреть кто ко мне логинился в /var/log/auth.log
Вроде ничего страшного не было, но обнаружил такую ошибку:
bad protocol version identification '' бла... бла... бла... мои ip
Полез в гугл, оказалась, что подобная проблема возникала у человека который пытался подключится telnet ом к SSH.

Так и оказалось, не так давно правил настройки для соединения со своим сервером, правил настройки кодировки и сохранял изменения и видать нечаянно переключил протокол вместо ssh стоял raw. Переключил тип протокола, указал правильный порт сохранил и все заработало.

воскресенье, 1 апреля 2012 г.

Apache2 + subversion установка на Debian

Предполагаю что apache2 у вас уже стоит ставим subversion + дополнительный модуль для apache
apt-get install subversion libapache2-svn 
Для самого репозитория понадобиться указать домашний каталог. Его можно указать абсолютно в любом месте. Я указал в качестве рабочего домашний каталог пользователя user. Создаем там каталог repos:

cd /home/user
mkdir repos

Далее создаем тестовый репозиторий
svnadmin create /home/user/repos/test
 
Меняем права для возможности доступа вэбсервера к каталогу
chown -R www-data: /home/user/repos
 
Копируем настройки модуля apache в бак и создаем файл со своими настройками
cp /etc/apache2/mods-available/dav_svn.conf /etc/apache2/mods-available/dav_svn.bak
nano  /etc/apache2/mods-available/dav_svn.conf

<Location /svn>
DAV svn
SVNParentPath /home/user/repos/
AuthType Basic
AuthName "My Repository"
AuthUserFile /home/user/passwd
Require valid-user</Location>
 
 

Далее создаем пользователя для http доступа к репозиторию и задаем пароль
htpasswd -c /home/user/passwd admin
 
Задействуем модули и перезапускаем apache
a2enmod dav dav_fs dav_svn
/etc/init.d/apache2 force-reload
 
  
Юзаем через http://адрес/svn/test

воскресенье, 18 марта 2012 г.

Ошибка: Sub-process /usr/bin/dpkg returned an error code (1)

Ошибка Sub-process /usr/bin/dpkg returned an error code (1) возникает при обновлении некоторых пакетов. У меня она возникла при обновлении mysql.

Решение нашел в интернете:
Удаляем:
# rm /var/lib/dpkg/info/имя_пакета*
# rm /var/cache/apt/archives/имя_пакета* 
 
В моем случае имя_пакета* было mysql-server-5.1



Ошибка: Stopping MySQL database server: mysqld failed!

Обычно шибка возникает если не имеет нужных привилегий debian-sys-maint

1. Сначала смотрим пароль в mcedit /etc/mysql/debian.cnf
Вырезаем его и сохраняем в файл
2. Заходим в консоль mysql: #mysql
3. Задаем привелегии:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY 'пароль' WITH GRANT OPTION;
4. Пробуем перезапустить.

Установка Webmin на Debian 6


Добавляем строки в /etc/apt/sources.list


$nano /etc/apt/sources.list

В конец добавим:


deb http://download.webmin.com/download/repository sarge contrib
deb http://webmin.mirror.somersettechsolutions.co.uk/repository sarge contrib

Сохраняем файл. Теперь необходимо установить GPG ключ которым подписан данный репозиторий:


$cd /root
$wget http://www.webmin.com/jcameron-key.asc && apt-key add jcameron-key.asc

Далее:

$apt-get update$apt-get install webmin

Ставим необходимые модули:


$apt-get install perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl


Установка завершена, теперь можно зайти в веб интерфейс по адресу: https://Ваш_IP:10000/
Для входа используйте логин и пароль root'a
После установки можно поменять шкурку панели, а также рекомендуется поменять порт и ограничить список ip адресов с которого он доступен.
Также возможна установка Webmin через deb пакет:

четверг, 15 марта 2012 г.

Вывод последних сообщений форума phpbb3 на сторонний сайт

Возникла задача вывода последних сообщений на главную страницу головного сайта. Сайт самописный и поэтому решил использовать собственный скрипт, а не поиск плагинов. Поизучав структуру базы форума обнаружил таблицу с названием phpbb_topics в ней находится 2 необходимых поля forum_id для генерации ссылки и topic_title для текста ссылки.

И собственно сам скрипт инклудим в нужном месте:

<?php

mb_internal_encoding("UTF-8");
mb_regex_encoding("UTF-8");

extract($_POST);
extract($_GET);

$dbhost = "localhost";

$dblogin = "Логин";
$dbpassword = "Пароль";
$dbname = "База с форумом";

$link = mysql_connect($dbhost, $dblogin, $dbpassword);

$db_selected = mysql_select_db($dbname, $link);
if (!$db_selected) {
    die ('Can\'t use foo : ' . mysql_error());
}


$result = mysql_query("SELECT topic_title, topic_id, forum_id FROM phpbb_topics ORDER BY topic_id DESC LIMIT 0, 5;");
while ($row = mysql_fetch_assoc($result))
{
$topic_title = $topic_title." <a href=\"http://Адрес сайта/viewtopic.php?f=".$row['forum_id']."&t=".$row['topic_id']."\">".$row['topic_title']."</a><br/>";
}

echo $topic_title;

?>

В скрипте стоит лимит на 5 сообщений и сортировкой по последним добавленным. Можно изменить по желанию.

Изменение стандартного соглашения при регистрации и полное отключение страницы с правилами phpbb3

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

Для начала рассмотрим способ замены стандартного соглашения. Для этого ищем файл с темой в центре администрирования Стили -> Шаблоны -> ucp_agreement.html
Ищем включение в <div class="content"> между условиями <!-- ELSE -->L_TERMS_OF_USE<!-- ENDIF -->

L_TERMS_OF_USE просто заменяем на свой текст

Теперь рассмотрим способ отключения вообще этой страницы. Делается это очень просто:

Открыть
includes/ucp/ucp_register.php

Найти
  $agreed   = (!empty($_POST['agreed'])) ? 1 : 0;

Заменить на
  $agreed   = 1;

Работа с phpbb3 из сторонних скриптов php: Часть 2 Создание поста

Итак, для создания поста опять же используем файл с функциями из первой части http://www.avesblog.ru/2012/03/phpbb3-php-1.html .

<?php
ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');

// The default phpBB inclusion protection - required
define('IN_PHPBB', true);
$phpbb_root_path = '';
$phpEx = substr(strrchr(__FILE__, '.'), 1);


include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
include($phpbb_root_path . 'phpBBFunctions.php');

$user->session_begin();
$auth->acl($user->data);
$user->setup();

// Backup the details of the logged in user
$backup = array(
  'user'   => $user,
  'auth'   => $auth,
);

// Get the data for the System user
$sql = "SELECT * FROM " . USERS_TABLE . " WHERE username = 'System'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

$user->data = array_merge($user->data, $row);
$auth->acl($user->data);

// Overwrite user's IP
$user->ip = '192.168.0.0';


$forumtoPost = 2; //Указываем id форума для постинга

$msgSubject = "Заголовок сообщения";
$msgText = "Текст в теле сообщения";

$newPostID = createPost ($forumtoPost,$msgSubject,$msgText);

echo "id поста $newPostID" .

// Restore the original backed up logged in user data
extract($backup);

?>


 Если используется одновременное создание форума и создание поста, то часть скрипта можно вынести отдельно до строки $forumtoPost = 2; а также последнюю строку.

Обе эти функции в принципе работают, но при их работе я замечал что не учитывается количество тем. То есть есть вариант столкнуться с проблемами, так что вы используете их на свой страх и риск.

среда, 14 марта 2012 г.

Работа с phpbb3 из сторонних скриптов php: Часть 1 Создание форума

Возникла идея плотно интегрировать свой сайт, а именно комментарии с форумом phpbb3. Начал поиски об его API, но толком никакой документации не обнаружил. Пришлось искать на зарубежных сайтах. Удалось найти одну статью на эту тему, но после их использования работает не совсем все ровно.

Для начала надо создать файл с функциями и перед вызовом скрипта включать его в код:

<?php

/**
 * Create a new category or forum on the fly
*/
function createPost ($forum,$msgSubject,$msgText) {

  // note that multibyte support is enabled here
  $my_subject   = utf8_normalize_nfc($msgSubject); // request_var('subject', '', true) was in place of $msgSubject


  $my_text   = utf8_normalize_nfc($msgText); // request_var('my_text', '', true) was in place of $msgText

  // variables to hold the parameters for submit_post
  $poll = $uid = $bitfield = $options = '';

  generate_text_for_storage($my_subject, $uid, $bitfield, $options, false, false, false);

  generate_text_for_storage($my_text, $uid, $bitfield, $options, true, true, true);

  $data = array(
    'forum_id'      => $forum,
    'icon_id'      => false,

    'enable_bbcode'      => true,
    'enable_smilies'   => true,
    'enable_urls'      => true,
    'enable_sig'      => true,

    'message'      => $my_text,
    'message_md5'   => md5($my_text),
          
    'bbcode_bitfield'   => $bitfield,
    'bbcode_uid'      => $uid,

    'post_edit_locked'   => 0,
    'topic_title'      => $my_subject,
    'notify_set'      => false,
    'notify'         => false,
    'post_time'       => 0,
    'forum_name'      => '',
    'enable_indexing'   => true,
  );

  submit_post('post', $my_subject, '', POST_NORMAL, $poll, $data);

  return $data['post_id'];

}

/**
 * Create a new category or forum on the fly
*/
function createCategoryForum($parent_id,$forum_perm_from,$forumType,$forumName,$forumDesc)
{

  global $db, $config, $auth, $phpEx, $phpbb_root_path, $cache;

  // The action. Always add when called in here
  $u_action = 'add';

  // The following code has been taken from around line 115 in includes/acp/acp_forums.php

  $forum_data = $errors = array();
   
  $forum_data += array(
    'parent_id'            => $parent_id,
    'forum_type'         => $forumType,
    'type_action'         => '',
    'forum_status'         => ITEM_UNLOCKED,
    'forum_parents'         => '',
    'forum_name'         => utf8_normalize_nfc($forumName),
    'forum_link'         => '',
    'forum_link_track'      => false,
    'forum_desc'         => utf8_normalize_nfc($forumDesc),
    'forum_desc_uid'      => '',
    'forum_desc_options'   => 7,
    'forum_desc_bitfield'   => '',
    'forum_rules'         => '',
    'forum_rules_uid'      => '',
    'forum_rules_options'   => 7,
    'forum_rules_bitfield'   => '',
    'forum_rules_link'      => '',
    'forum_image'         => '',
    'forum_style'         => 0,
    'display_subforum_list'   => false,
    'display_on_index'      => false,
    'forum_topics_per_page'   => 0,
    'enable_indexing'      => true,
    'enable_icons'         => false,
    'enable_prune'         => false,
    'enable_post_review'   => true,
    'prune_days'         => 7,
    'prune_viewed'         => 7,
    'prune_freq'         => 1,
    'prune_old_polls'      => false,
    'prune_announce'      => false,
    'prune_sticky'         => false,
    'forum_password'      => '',
    'forum_password_confirm'=> '',
    'forum_password_unset'   => false,
  );

  // Use link_display_on_index setting if forum type is link
  if ($forum_data['forum_type'] == FORUM_LINK)
  {
    $forum_data['display_on_index'] = false;
    // Linked forums are not able to be locked...
    $forum_data['forum_status'] = ITEM_UNLOCKED;
  }

  $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? false : false;

  // Get data for forum rules if specified...
  if ($forum_data['forum_rules'])
  {
    generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], false, false, false);
  }

  // Get data for forum description if specified
  if ($forum_data['forum_desc'])
  {
    generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], false, false, false);
  }

  $errors = update_forum_data($forum_data);

  if (!sizeof($errors))
  {

    // Copy permissions? // if statement removed below so permissions are copied

    // From the mysql documentation:
    // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14.
    // Due to this we stay on the safe side if we do the insertion "the manual way"

    // Copy permisisons from/to the acl users table (only forum_id gets changed)
    $sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting
      FROM ' . ACL_USERS_TABLE . '
      WHERE forum_id = ' . $forum_perm_from;
    $result = $db->sql_query($sql);

    $users_sql_ary = array();
    while ($row = $db->sql_fetchrow($result))
    {
      $users_sql_ary[] = array(
        'user_id'         => (int) $row['user_id'],
        'forum_id'         => (int) $forum_data['forum_id'],
        'auth_option_id'   => (int) $row['auth_option_id'],
        'auth_role_id'      => (int) $row['auth_role_id'],
        'auth_setting'      => (int) $row['auth_setting']
      );
    }
    $db->sql_freeresult($result);

    // Copy permisisons from/to the acl groups table (only forum_id gets changed)
    $sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting
      FROM ' . ACL_GROUPS_TABLE . '
      WHERE forum_id = ' . $forum_perm_from;
    $result = $db->sql_query($sql);

    $groups_sql_ary = array();
    while ($row = $db->sql_fetchrow($result))
    {
      $groups_sql_ary[] = array(
        'group_id'         => (int) $row['group_id'],
        'forum_id'         => (int) $forum_data['forum_id'],
        'auth_option_id'   => (int) $row['auth_option_id'],
        'auth_role_id'      => (int) $row['auth_role_id'],
        'auth_setting'      => (int) $row['auth_setting']
      );
    }
    $db->sql_freeresult($result);

    // Now insert the data
    $db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary);
    $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
    cache_moderators();
    // removed } from here that was related to permissions if above iain

    $auth->acl_clear_prefetch();
    $cache->destroy('sql', FORUMS_TABLE);

    return $forum_data['forum_id'];

  } 

  else
  {
    echo "Error!!" . print_r($errors);

    return 0;
  }

}

// The following function has been taken from acp_forums.php file / acp_forums class and no changes have been made by me!

   /**
   * Update forum data
   */
   function update_forum_data(&$forum_data)
   {
      global $db, $user, $cache;

      $errors = array();

      if (!$forum_data['forum_name'])
      {
         $errors[] = $user->lang['FORUM_NAME_EMPTY'];
      }

      if (utf8_strlen($forum_data['forum_desc']) > 4000)
      {
         $errors[] = $user->lang['FORUM_DESC_TOO_LONG'];
      }

      if (utf8_strlen($forum_data['forum_rules']) > 4000)
      {
         $errors[] = $user->lang['FORUM_RULES_TOO_LONG'];
      }

      if ($forum_data['forum_password'] || $forum_data['forum_password_confirm'])
      {
         if ($forum_data['forum_password'] != $forum_data['forum_password_confirm'])
         {
            $forum_data['forum_password'] = $forum_data['forum_password_confirm'] = '';
            $errors[] = $user->lang['FORUM_PASSWORD_MISMATCH'];
         }
      }

      if ($forum_data['prune_days'] < 0 || $forum_data['prune_viewed'] < 0 || $forum_data['prune_freq'] < 0)
      {
         $forum_data['prune_days'] = $forum_data['prune_viewed'] = $forum_data['prune_freq'] = 0;
         $errors[] = $user->lang['FORUM_DATA_NEGATIVE'];
      }

      $range_test_ary = array(
         array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'),
      );
      validate_range($range_test_ary, $errors);



      // Set forum flags
      // 1 = link tracking
      // 2 = prune old polls
      // 4 = prune announcements
      // 8 = prune stickies
      // 16 = show active topics
      // 32 = enable post review
      $forum_data['forum_flags'] = 0;
      $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0;
      $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0;
      $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
      $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
      $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
      $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;

      // Unset data that are not database fields
      $forum_data_sql = $forum_data;

      unset($forum_data_sql['forum_link_track']);
      unset($forum_data_sql['prune_old_polls']);
      unset($forum_data_sql['prune_announce']);
      unset($forum_data_sql['prune_sticky']);
      unset($forum_data_sql['show_active']);
      unset($forum_data_sql['enable_post_review']);
      unset($forum_data_sql['forum_password_confirm']);

      // What are we going to do tonight Brain? The same thing we do everynight,
      // try to take over the world ... or decide whether to continue update
      // and if so, whether it's a new forum/cat/link or an existing one
      if (sizeof($errors))
      {
         return $errors;
      }

      // As we don't know the old password, it's kinda tricky to detect changes
      if ($forum_data_sql['forum_password_unset'])
      {
         $forum_data_sql['forum_password'] = '';
      }
      else if (empty($forum_data_sql['forum_password']))
      {
         unset($forum_data_sql['forum_password']);
      }
      else
      {
         $forum_data_sql['forum_password'] = phpbb_hash($forum_data_sql['forum_password']);
      }
      unset($forum_data_sql['forum_password_unset']);

      if (!isset($forum_data_sql['forum_id']))
      {
         // no forum_id means we're creating a new forum
         unset($forum_data_sql['type_action']);

         if ($forum_data_sql['parent_id'])
         {
            $sql = 'SELECT left_id, right_id, forum_type
               FROM ' . FORUMS_TABLE . '
               WHERE forum_id = ' . $forum_data_sql['parent_id'];
            $result = $db->sql_query($sql);
            $row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);

            if (!$row)
            {
               trigger_error($user->lang['PARENT_NOT_EXIST'] . "id = $parent_id", E_USER_WARNING);
            }

            if ($row['forum_type'] == FORUM_LINK)
            {
               $errors[] = $user->lang['PARENT_IS_LINK_FORUM'];
               return $errors;
            }

            $sql = 'UPDATE ' . FORUMS_TABLE . '
               SET left_id = left_id + 2, right_id = right_id + 2
               WHERE left_id > ' . $row['right_id'];
            $db->sql_query($sql);

            $sql = 'UPDATE ' . FORUMS_TABLE . '
               SET right_id = right_id + 2
               WHERE ' . $row['left_id'] . ' BETWEEN left_id AND right_id';
            $db->sql_query($sql);

            $forum_data_sql['left_id'] = $row['right_id'];
            $forum_data_sql['right_id'] = $row['right_id'] + 1;
         }
         else
         {
            $sql = 'SELECT MAX(right_id) AS right_id
               FROM ' . FORUMS_TABLE;
            $result = $db->sql_query($sql);
            $row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);

            $forum_data_sql['left_id'] = $row['right_id'] + 1;
            $forum_data_sql['right_id'] = $row['right_id'] + 2;
         }

         $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql);
         $db->sql_query($sql);

         $forum_data['forum_id'] = $db->sql_nextid();

         add_log('admin', 'LOG_FORUM_ADD', $forum_data['forum_name']);
      }
      else
      {
         $row = get_forum_info($forum_data_sql['forum_id']);

         if ($row['forum_type'] == FORUM_POST && $row['forum_type'] != $forum_data_sql['forum_type'])
         {
            // Has subforums and want to change into a link?
            if ($row['right_id'] - $row['left_id'] > 1 && $forum_data_sql['forum_type'] == FORUM_LINK)
            {
               $errors[] = $user->lang['FORUM_WITH_SUBFORUMS_NOT_TO_LINK'];
               return $errors;
            }

            // we're turning a postable forum into a non-postable forum
            if ($forum_data_sql['type_action'] == 'move')
            {
               $to_forum_id = request_var('to_forum_id', 0);

               if ($to_forum_id)
               {
                  $errors = $this->move_forum_content($forum_data_sql['forum_id'], $to_forum_id);
               }
               else
               {
                  return array($user->lang['NO_DESTINATION_FORUM']);
               }
            }
            else if ($forum_data_sql['type_action'] == 'delete')
            {
               $errors = $this->delete_forum_content($forum_data_sql['forum_id']);
            }
            else
            {
               return array($user->lang['NO_FORUM_ACTION']);
            }

            $forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0;
            $forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = '';
         }
         else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_LINK)
         {
            // Has subforums?
            if ($row['right_id'] - $row['left_id'] > 1)
            {
               // We are turning a category into a link - but need to decide what to do with the subforums.
               $action_subforums = request_var('action_subforums', '');
               $subforums_to_id = request_var('subforums_to_id', 0);

               if ($action_subforums == 'delete')
               {
                  $rows = get_forum_branch($row['forum_id'], 'children', 'descending', false);

                  foreach ($rows as $_row)
                  {
                     // Do not remove the forum id we are about to change. ;)
                     if ($_row['forum_id'] == $row['forum_id'])
                     {
                        continue;
                     }

                     $forum_ids[] = $_row['forum_id'];
                     $errors = array_merge($errors, $this->delete_forum_content($_row['forum_id']));
                  }

                  if (sizeof($errors))
                  {
                     return $errors;
                  }

                  if (sizeof($forum_ids))
                  {
                     $sql = 'DELETE FROM ' . FORUMS_TABLE . '
                        WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
                     $db->sql_query($sql);

                     $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
                        WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
                     $db->sql_query($sql);

                     $sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
                        WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
                     $db->sql_query($sql);

                     // Delete forum ids from extension groups table
                     $sql = 'SELECT group_id, allowed_forums
                        FROM ' . EXTENSION_GROUPS_TABLE;
                     $result = $db->sql_query($sql);

                     while ($_row = $db->sql_fetchrow($result))
                     {
                        if (!$_row['allowed_forums'])
                        {
                           continue;
                        }

                        $allowed_forums = unserialize(trim($_row['allowed_forums']));
                        $allowed_forums = array_diff($allowed_forums, $forum_ids);

                        $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . "
                           SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "'
                           WHERE group_id = {$_row['group_id']}";
                        $db->sql_query($sql);
                     }
                     $db->sql_freeresult($result);

                     $cache->destroy('_extensions');
                  }
               }
               else if ($action_subforums == 'move')
               {
                  if (!$subforums_to_id)
                  {
                     return array($user->lang['NO_DESTINATION_FORUM']);
                  }

                  $sql = 'SELECT forum_name
                     FROM ' . FORUMS_TABLE . '
                     WHERE forum_id = ' . $subforums_to_id;
                  $result = $db->sql_query($sql);
                  $_row = $db->sql_fetchrow($result);
                  $db->sql_freeresult($result);

                  if (!$_row)
                  {
                     return array($user->lang['NO_FORUM']);
                  }

                  $subforums_to_name = $_row['forum_name'];

                  $sql = 'SELECT forum_id
                     FROM ' . FORUMS_TABLE . "
                     WHERE parent_id = {$row['forum_id']}";
                  $result = $db->sql_query($sql);

                  while ($_row = $db->sql_fetchrow($result))
                  {
                     $this->move_forum($_row['forum_id'], $subforums_to_id);
                  }
                  $db->sql_freeresult($result);

                  $sql = 'UPDATE ' . FORUMS_TABLE . "
                     SET parent_id = $subforums_to_id
                     WHERE parent_id = {$row['forum_id']}";
                  $db->sql_query($sql);
               }

               // Adjust the left/right id
               $sql = 'UPDATE ' . FORUMS_TABLE . '
                  SET right_id = left_id + 1
                  WHERE forum_id = ' . $row['forum_id'];
               $db->sql_query($sql);
            }
         }
         else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_POST)
         {
            // Changing a category to a forum? Reset the data (you can't post directly in a cat, you must use a forum)
            $forum_data_sql['forum_posts'] = 0;
            $forum_data_sql['forum_topics'] = 0;
            $forum_data_sql['forum_topics_real'] = 0;
            $forum_data_sql['forum_last_post_id'] = 0;
            $forum_data_sql['forum_last_post_subject'] = '';
            $forum_data_sql['forum_last_post_time'] = 0;
            $forum_data_sql['forum_last_poster_id'] = 0;
            $forum_data_sql['forum_last_poster_name'] = '';
            $forum_data_sql['forum_last_poster_colour'] = '';
         }

         if (sizeof($errors))
         {
            return $errors;
         }

         if ($row['parent_id'] != $forum_data_sql['parent_id'])
         {
            $errors = $this->move_forum($forum_data_sql['forum_id'], $forum_data_sql['parent_id']);
         }

         if (sizeof($errors))
         {
            return $errors;
         }

         unset($forum_data_sql['type_action']);

         if ($row['forum_name'] != $forum_data_sql['forum_name'])
         {
            // the forum name has changed, clear the parents list of all forums (for safety)
            $sql = 'UPDATE ' . FORUMS_TABLE . "
               SET forum_parents = ''";
            $db->sql_query($sql);
         }

         // Setting the forum id to the forum id is not really received well by some dbs. ;)
         $forum_id = $forum_data_sql['forum_id'];
         unset($forum_data_sql['forum_id']);

         $sql = 'UPDATE ' . FORUMS_TABLE . '
            SET ' . $db->sql_build_array('UPDATE', $forum_data_sql) . '
            WHERE forum_id = ' . $forum_id;
         $db->sql_query($sql);

         // Add it back
         $forum_data['forum_id'] = $forum_id;

         add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']);
      }

      return $errors;
   }


// The function below has been taken from adm/index.php and hasn't been changed either. Iain

/**
* Checks whatever or not a variable is OK for use in the Database
* param mixed $value_ary An array of the form array(array('lang' => ..., 'value' => ..., 'column_type' =>))'
* param mixed $error The error array
*/
function validate_range($value_ary, &$error)
{
   global $user;
 
   $column_types = array(
      'BOOL'   => array('php_type' => 'int',       'min' => 0,             'max' => 1),
      'USINT'   => array('php_type' => 'int',      'min' => 0,             'max' => 65535),
      'UINT'   => array('php_type' => 'int',       'min' => 0,             'max' => (int) 0x7fffffff),
      'INT'   => array('php_type' => 'int',       'min' => (int) 0x80000000,    'max' => (int) 0x7fffffff),
      'TINT'   => array('php_type' => 'int',      'min' => -128,            'max' => 127),
    
      'VCHAR'   => array('php_type' => 'string',    'min' => 0,             'max' => 255),
   );
   foreach ($value_ary as $value)
   {
      $column = explode(':', $value['column_type']);
      $max = $min = 0;
      $type = 0;
      if (!isset($column_types[$column[0]]))
      {
         continue;
      }
      else
      {
         $type = $column_types[$column[0]];
      }

      switch ($type['php_type'])
      {
         case 'string' :
            $max = (isset($column[1])) ? min($column[1],$type['max']) : $type['max'];
            if (strlen($value['value']) > $max)
            {
               $error[] = sprintf($user->lang['SETTING_TOO_LONG'], $user->lang[$value['lang']], $max);
            }
         break;

         case 'int':
            $min = (isset($column[1])) ? max($column[1],$type['min']) : $type['min'];
            $max = (isset($column[2])) ? min($column[2],$type['max']) : $type['max'];
            if ($value['value'] < $min)
            {
               $error[] = sprintf($user->lang['SETTING_TOO_LOW'], $user->lang[$value['lang']], $min);
            }
            else if ($value['value'] > $max)
            {
               $error[] = sprintf($user->lang['SETTING_TOO_BIG'], $user->lang[$value['lang']], $max);
            }
         break;
      }
   }
}


?>
Файл огромных размеров, разбирать его правда без надобности лучше подробнее описать примеры работ самих функций.

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

Приведу пример создания форума:
<?php


ini_set('error_reporting', E_ALL);
ini_set('display_errors', 'On');


// The default phpBB inclusion protection - required
define('IN_PHPBB', true);
$phpbb_root_path = ''; // путь к форуму относительно скрипта
$phpEx = substr(strrchr(__FILE__, '.'), 1);

//Подключение к функциям форума
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
include($phpbb_root_path . 'phpBBFunctions.php'); // файл с функциями     //см. предидущий код


$user->session_begin();
$auth->acl($user->data);
$user->setup();
//Сохранение текущей сессии пользователя
$backup = array(
  'user'   => $user,
  'auth'   => $auth,
);

// Получение данных о пользователе "System"
$sql = "SELECT * FROM " . USERS_TABLE . " WHERE username = 'System'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

$user->data = array_merge($user->data, $row);
$auth->acl($user->data);

// Задаем ip адрес пользователя можно указать любой
$user->ip = '192.168.0.0';

// ID родительского форума
$forumParentID = 15;

// Форум с которого копируем права(т.е. подфорум который для этого //специально и создали)
$forumPpermFrom = 2;
//Тип форума FORUM_CAT категория, FORUM_POST обычный форум, FORUM_LINK //ссылка на форум
$forumType = FORUM_POST;

// Имя форума
$forumName = "Тестовый форум";
$forumDesc = "Сообщение внизу форума Описание";

// Check that user (System) has permissions to create forums. Taken from includes/acp/acp_forums.php around line 71
// Error trigger taken out and replaced with simple echo. The error shouldnevr happen but it's just in case..
if (!$auth->acl_get('a_forumadd'))
{
  echo "ERROR! Problem with forum creation permissions for user";
}

$newForumID = createCategoryForum($forumParentID,$forumPpermFrom,$forumType,$forumName,$forumDesc);

echo "Форум создан и имеет ID = $newForumID";

// Восстановление данных сессии
extract($backup);


?>

воскресенье, 11 марта 2012 г.

Ошибка: mpt-statusd: detected non-optimal RAID status

Ошибка возникает на виртуальных Vmware Debian серверах. По информации из интернет причиной является LSI адаптер который создается по умолчанию.
До определенного времени я на нее внимания не обращал пока не подключил редирект с ящика на который он слал информацию об ошибке каждые 2 часа. Пришлось эту проблему решать.

Решение в удалении этой службы.
Для начала останавливаем:
/etc/init.d/mpt-statusd stop
и потом чистим
update-rc.d-insserv -f mpt-statusd remove

У меня проблема после этого решилась

пятница, 9 марта 2012 г.

Маленькая таблеточка от SQL injection

Немного порывшись в интернете наткнулся на небольшое решение для защиты от sql injection. От злобных кулхацкеров он врядли спасет, но по крайней мере часть школоты можно отвадить от вашего сайта. Решение следующее. В самом верху вашего файла index.php или другого основного файла движка, можно даже до подключения всех конфигов и файлов с функциями вставить следующий код.

$get_ar = array_values($_GET);
$c_a_g = count($get_ar);
for ($i = 0;$i < $c_a_g;$i++){
if(eregi('union(.*)select',$get_ar[$i])){ header("Location: http://xakep.ru"); exit; }
if(eregi('order(.*)by',$get_ar[$i])){ header("Location: http://xakep.ru"); exit; }
}
$post_ar = array_values($_POST);
$c_a_p = count($post_ar);
for ($i = 0;$i < $c_a_p;$i++){
if(eregi('union(.*)select',$post_ar[$i])){ header("Location: http://xakep.ru"); exit; }
if(eregi('order(.*)by',$post_ar[$i])){ header("Location: http://xakep.ru"); exit; }
}

Данный способо будет обрабатывать все post и get переменные которые передаются скрипту и при попытке выполнить команду например union select будет происходить редирект на сайт журнала Хакер, либо можно его поменять на свой сайт и это будет аналогично переходу на вашу главную страницу.

четверг, 8 марта 2012 г.

Google советует как и какой лучше разместить рекламный блок для увеличения прибыли.

Зашел один раз в свой аккаунт Adsense и был приятно удивлен. В верху страницы красовалась надпись:"Рекомендации". В этом блоке было написано, что я могу увеличить свой доход с этого рекламного блока на 35-65 %, если изменю его.



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

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

Phpbb3 и Loginza: Ошибки возникающие при интеграции

При интеграции с loginza у меня возникло 4 ошибки.
1. При установке через AutoMOD возникла ошибка в поиске строки с вставкой js в файл overall_header.html. Я нашел эту строку со скриптом forum_fn.js и вставил в ручную. Так как ошибок больше не было я нажал на force install.

2. Вторая и третья ошибки были очень похожи. Они состояли в отсутствии значания по умолчанию в полях loginza_identity loginza_provider в таблице phpbb_users.
Возникала следующая ошибка Field 'loginza_identity' doesn't have a default value и Field 'loginza_provider' doesn't have a default value при регистрации пользователя обычным способом. Решение проблемы принудительное изменение значения по умолчанию этих полей на 0 через phpMyAdmin.

3. Ну и последняя ошибка возникла по глупости, но почему то в интрнете вообще нигде не описанная. В форме регистрации где должен был появиться виджет появлялась ошибка: Error: token_url is empty. После установки loginza автоматически предлагается скачать архив с файлами. И эти файлы надо закинуть в каталог с форумом. Проблема решиться.