Как стать автором
Поиск
Написать публикацию
Обновить

Как я был опенсорсником…

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

Году наверное в 2003-м… к тому времени я уже довольно таки долгое время являлся пользователем дистрибутива Slackware, так что о том как собирать ПО я знал уже неплохо, но вот знания «си» мне сильно не хватало (забегая вперед признаюсь, я и сейчас то его не знаю). Тем не менее сильно хотелось добавить одну полезную для меня фичу в Midnight Commander. А именно опцию сортировки файлов, когда первыми идут «исполняемые», как это сделано например в far. С помощью аськи и глупых вопросов к приятелям-сишникам, худо бедно удалось сделать то что хотел… хотя и криво…
Больше к mc я не притрагивался остановившись на достигнутом…

В какой то момент времени, года 2-3 назад, я стал счастливым владельцем забавной белой коробочки, с гордым названием — Asus WL500g Premium. Т.к. с родным mc из репозитария oleo все было совсем «не очень», то пришлось садиться и пилить чтобы можно было худо бедно иметь возможность работать с именами в UTF-8… Попилить пришлось изрядно ибо с UTF-8 патчами от Дебиана и FC собираться mc на коробочке наотрез отказался, было не просто, но я таки асилил… учитывая практически нулевое знание си, процесс несколько затянулся. Но когда все было закончено результат в виде готового пакета я выложил на соответствующем форуме.

В результате ковыряний я не изучил си, просто понял что в принципе достаточно немного упорства и терпения чтобы делать небольшие патчи. Главное слишком сильно не ломать всю систему и пользоваться приемами XP. Так я и решился взяться за первый проект под «коробочку» это легкий DC++ клиент который мог бы работать на совсем дохлом железе, имел бы хорошую поддержку национальных языков и мог раздавать и принимать файлы частями и из разных источников. В качестве концепции была выбран подход утилиты wget, т.е. отдаем ссылку утилите, а она дальше занимается всем сама и завершает работу, когда дело будет сделано. Так родилась идея консольного DC++ клиента dcget. Отсмотрев множество легковесных открытых проектов, был найден ShakesPeer, который является клиент-серверной реализацией DC++ клиента, в основе которого лежит общение через сокеты UI и собственно движком который занимается закачкой и раздачей контента.
Вот его то я и решил форкнуть, добавив недостающего мне функционала. Задача была не такая сложная, но навигация по чужому коду доставляла множество неудобств, требовался подходящий редактор. Мне очень не хватало редактора похожего на редактор far со сходными сочетаниями клавиш, и его возможностями работы с исходным кодом, вроде перехода к определению функций и прочих приятных мелочей присущим удобным редакторам. Чтобы совсем уж не бедствовать а настроил в vim необходимые средства превращающие его в IDE и потихоньку им пользовался. Но тяжело переучивать старую собаку новым трюкам. Помнить на автомате 3 набора горячих клавиш для меня оказалось просто непосильной задачей, причем бывало что поработав в far я на автомате портил текст в vim и наоборот… бывало что без мата не обходилось :).

Тем временем я наткнулся на новость на opennet о том, что появилась новая версия mc с дополнительными патчами, вроде раскраски файлов и прочих полезных мелочей, (которые кстати говоря уже были в моей сборке под «коробочку») и решил связаться с коммандой в плане «поделиться опытом» и отдать пару своих мелких патчей из сборки под WL500gP. Как оказалось ребята были «дружный молодым коллективом» (tm) с которым просто найти общий язык и понимание. Все что нужно было сделать это сделать пару приватный-публичный ключ и отправить публичный ключ Патрику Винертзу чтобы меня зарегистрировали на сайте Миднайт коммандера и я получил доступ на запись в git репозтарий.

Итак, что было в сухом остатке: неумение пользоваться git, незнание языка си, опыт программирования на многих языках и большое желание сделать mcedit более удобным в использовании имеющим тот же набор фич что и far. Первый принятый мой патч был как раз патч реализующий отображение исполняемых файлов в начале списка. На этот раз патч был реализован идеологически верно и не являлся грязным хаком. К счастью в команде были те кто отсматривал мои патчи и проводил большую работу по ревизии моего кода без них я бы наверное не осилил бы и десятой части написанного. В результате у меня теперь есть редактор полностью удовлетворяющий мои потребности в плане использования его в качестве IDE. И что самое интересное практически все что мне нужно там и так было, только зарыто так глубоко что и не добраться т.к. не выведено было наружу. В общем, чем больше капался с текстом редактора, тем больше находил реализованных фич, иногда бывало забавно, что доделав очередной патч находил подобную же реализацию, в самом неожиданном месте, после чего удалял свое и дорабатывал то что есть… Подход в основном был такой, по максимуму сделать свой код простым в дальнейшем сопровождении и по максимуму вписывающимся в общую концепцию и стиль текущего проекта.

Кстати говоря, писать открытый код, это по сути халява с точки зрения программиста, все что нужно сделать это найти где нужный тебе код уже был написан до тебя и удачно скопипастить :)

Работа в команде это конечно отдельная тема… интереснейший опыт с точки зрения программиста — ревизии кода, обсуждения задач и способов возможной реализации и прочия-прочия-прочия…

PS: вот так вот, получив нужный и удобный инструмент для работы над своей поделкой dcget потерял, практически полный, к ней интерес… се ля ви :)

Нейронная сеть на Javascript — обмаН да и только!

Сегодня прочитал статью: OCR и нейронная сеть в JavaScript [перевод]

Восхитился! Неужели такое возможно?
Решил попробовать скачать, установить и настроить все это дело у себя… но открыв ссылку на демо скрипт заметил несколько не соответсвий:

1. Что я обычно делаю с непонятными страницами в интернете? Правильно, наверное многие так делают — смотрю исходный код странички и что я там вижу…:
image

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

2. поехали дальше

сохранив страничку полностью смотрим что у нас за изображения:

cub6.gif (имя картинки в соответствии с кодом на картинке) Сама картинка не имеет фон…
и
image.psp (черно-белая картинка с таким же кодом) Эта картинка подгружается позже всех — свидетельствуя тому, что она обрабатывается функциями пхп, а именно создается и применяются фильтры…

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

Киньте в меня камень если я не прав!!!

Про маркетинг и маркетинг в сфере ИТ.

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

Я хочу высказать свою точку зрения на всё это. Начнём с того, что маркетинг, это не наука, как говорят об этом вторые. Хотя многие иностранные системы обучения принимают противоположную сторону. Что бы не разжигать холиваров уточню, я маркетинг не принимаю как науку. Для меня это чисто прикладные методы. Какие то из них работают, какие то нет.

Так что же такое маркетинг? Литература даёт нам совершенно разные определения. Почитать их можно хотя бы даже в википедии. Повторяться не вижу смысла. Скажу лишь что слово это имеет английские корни, а именно герундий английского слова «рынок» — market. Т.е. Маркетинг, это процесс. Процесс поиска рынка. Вот собственно его суть. И именно поэтому основы маркетинга надо знать любому предпринимателю. Вот в «научную» сторону лезть совершенно нет смысла.

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

Идут украинец и еврей по пустыне, у еврея мешок золота, у украинца мешок сала. Идут долго, жажда и голод одолевают, еврей и просит: «Поделись сальцем, сил нет», а тот и отвечает: «А давайте по вашему? Как на рынке?». Ну куда деваться, еврей соглашается:
-По чём шмат сала?
-Мешок золота!
-Почему ж так дорого?!
-А ты пройдись по рынку, найди дешевле.


Иначе говоря, есть рынок где у предпринимателя может быть огромная конкуренция, а может быть он сможет найти рынок, где и шмат сала уйдёт за мешок золота. Поиск таких «рынков», называется сегментирование. А сегмент рынка можно назвать «ниша». Цель маркетинга определяется ещё уже — найти свою нишу.

И вот по этому я с трудом могу назвать маркетинг наукой. Нет никакой точно формулы как найти нишу. Есть методы помогающие в этом, есть методы работы с уже рабочей нишей, но нет алгоритма по которому мы возьмём, подставим в формулу Х-наш продукт, Y-ожидания инвесторов, и в итоге получим результат — вот ваша целевая аудитория.

И продажа программных продуктов, да и продажи вообще, это больше песня о маркетинге, как о процессе поиска покупателей, а не о программировании. И именно этому надо уделять особое внимание — поиску ниши. Не рекламе, ни прямым рассылкам, а поиску ниши, это самая сложная часть дела. «Атаковать» можно только тогда, когда знаешь кого, не правда ли? Найдя своего «врага» Вам не придётся атаковать по всем фронтам всех тратя силы и раздражая мирных жителей, вы ведь не знаете кто из них «враг»? :) Говоря реальными словами, демпингуя(снижая цену) вы идёте к поражению. Всегда найдётся тот кто предложит ту же цену и ещё «что-то». А вот в Вашей нише, найди Вы её, конкурентов может и не быть.

Рынок программных продуктов, имеет не самый низкий порог вхождения(минимальные инвестиции), но и не самый высокий. Замахиваться на всех сразу, это очень дорого. Это горизонтальный рынок, на этом рынке царят корпорации, и уже окрепшие компании, в т.ч. и стартапы. Ваша цель, Ваша ниша, должна быть меньше, это области которые не могут или не хотят охватывать большие корпорации, а вот Вы и Ваша команда может и охватит. Это горизонтальный рынок. Примеры?

Зачем нам замахиваться на сегмент бухгалтерского софта, там достаточно крупных игроков, это «Акулы». За то они не охватывают особенности предприятий, тут Ваша добыча, как «рыбы-прилипалы». Акула не может скушать всё, остаются куски проходящие сквозь зубы. И это не такая маленькая часть пищи. Дописать функционал для одной организации, для другой, для третьей. Потом объединить в себе и мы получим новый программный продукт, к не менее крупному бухгалтерскому софту.

Спасибо за внимание, надеюсь с помощью Ваших вопросов, я смогу написать что-то действительно полезное. ;)

Gasbuddy.Ru – снизим цены на бензин!

GasBuddy.Ru
GasBuddy.Ru – проект, который предлагает простой механизм, позволяющий каждому из нас влиять (пусть и косвенно) на стоимость бензина на АЗС Нашей Страны.

Каждого автомобилиста вполне резонно волнует проблема стоимости бензина на рынке России. Среди стран-экспортеров Россия уверенно лидирует по стоимости топлива на внутреннем рынке! Хотя, казалось, при таких сверхдоходах от экспорта нефти должно быть ровно наоборот. Мы давно привыкли считать, что от нас мало что зависит. Однако существует яркий пример, показывающий, что каждый из нас может повлиять на ситуацию! В США существует Интернет-ресурс gasbuddy.com, пользующийся огромной популярностью среди американских автомобилистов. В основе его лежит идея: «Дорогие и некачественные заправки лучше объезжать стороной». Сам ресурс предлагает пользователям различные сервисы, с помощью которых они могут быть в курсе ситуации на топливном рынке. Мы решили принести идею в Россию, т.к. для нас проблема стоимости бензина более чем актуальна.

GasBuddy.Ru – информационный портал, предоставляющий автомобилистам множество удобных сервисов.
Каждый пользователь может принимать активное участие в жизни проекта и самостоятельно добавлять АЗС и цены на бензин на конкретной станции. На сайте реализована система рейтингов, на основе которой производится поощрение пользователей за активное участие в жизни проекта.

Расширенный механизм поиска позволяет находить АЗС с точным указанием места на карте Google, видов топлива, цен на бензин, перечня услуг, предоставляемых АЗС. База АЗС уже охватывает многие регионы России и постоянно расширяется! Нашей целью является создание наиболее полной базы автозаправочных станций России и предоставление пользователям удобных инструментов поиска и публикации цен на бензин на всех АЗС страны. На основе опубликованных данных планируется производить сбор и отображение статистики по колебаниям стоимости бензина в тех или иных регионах России.

Система рейтинга и отзывов об АЗС дает возможность каждому пользователю оценить заправку по десятибальной шкале и оставить свое мнение о ней. Таким образом, для любого города всегда можно узнать «белый список» АЗС, построенный самими автомобилистами, а прежде, чем заправиться на той или иной станции, можно узнать мнение других пользователей о качестве предоставляемых на ней услуг.
Для обсуждения сайта и проблем топливного рынка на сайте реализован форум.
На GasBuddy.Ru любой пользователь может получить приятный сюрприз. Ведь каждый месяц один из наиболее активных участников сайта награждается топливной картой!

Учет VPN сессий в PoPToP PPTP сервере под FreeBSD 6.3

Жил-был маленький сервер под FreeBSD 6.3 и выполнял он всякие разные функции, в том числе и функцию VPN сервера для того чтобы измученые отдыхом сотрудники могли удаленно подключится к корпоративной сетке и наконец-то поработать. :)
Сначала количество сотрудников было небольшим и все всех устраивало. Со временем, когда уже значительная доля сотрудников обзавелась vpn аккаунтами встал вопрос учета этих самых подключений.
В качестве VPN сервера крутился PoPToP cо следующими конфигами:

/usr/local/etc/pptpd.conf
options /etc/ppp/options.pptpd

/usr/local/etc/pptpd.conf
proxyarp
+MSChap-V2 mppe-128 mppe-stateless
nodefaultroute
logfile /var/log/vpn.log
ms-dns 192.168.7.1
auth


/usr/local/etc/ppp.conf
pptp:
enable dns
enable nat
enable proxy
set ifaddr 192.168.7.1 192.168.7.241-254 255.255.255.0 # ИП сервера Пул адресов Маска
set dns 192.168.7.1 # адрес DNS
set timeout 300 #таймаут простоя до разрыва соединения
enable MSChapV2 # протокол по которому шифруемся
set nbns 192.168.7.1 # WINS


/usr/local/etc/ppp.secret
Формат файла
логин пароль ип адрес или диапазон из выделенного адресного пространства (см ppp.conf)
test test 192.168.7.240-192.168.7.242
test1 test123 192.168.7.245


Если кто хочет установить так же, установка проста до безобразия:
cd /usr/ports/net/poptop
make install clean

Ну и для автозапуска демона добавить в /etc/rc.conf
pptpd_enable="YES"

На этом сервере также висит связка АМР (Apache, МуSQL, PHP).
Поэтому было решено пойти по пути наименьшего сопротивления. Так как бешенный прирост в кол-ве VPN пользователей не ожидается то было решено не переделывать все (Я уже слышу выкрики из зала по поводу mpd+Radius и т.д.), а просто создать базу в мускуле и заносить данные о сессииях туда. А уж написать веб-обвязку на пхп для манипулирования этими данными не составит труда.

Создаем базу
Базу назовем к примеру vpn
В ней 2 таблички
users и sessions
Назаначение полей, я думаю, прозрачно.
Создаем пользователя для базы
например логин- vpn, пасс- vpn с правом доступа только с локалхоста.
Скрипт создания базы — vpn.sql
CREATE DATABASE `vpn` ;
USE `vpn`;

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(15) DEFAULT NULL,
`nick` varchar(20) DEFAULT NULL,
`username` varchar(50) DEFAULT NULL,
`date` date DEFAULT NULL,
`time` time DEFAULT NULL,
`online` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9;

CREATE TABLE `sessions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(15) DEFAULT NULL,
`nick` varchar(20) DEFAULT NULL,
`date` date DEFAULT NULL,
`time` time DEFAULT NULL,
`uptime` time DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=86;


Скриптыдобавления информации
В папке /etc/ppp
создаем следующие файлики которые будут вызывать наши скрипты.
За подробностями man ppp. ;)

ppp.linkup
pptp:
! sh -c "/etc/ppp/vpn_up.sh USER HISADDR"


ppp.linkdown
pptp:
! sh -c "/etc/ppp/vpn_down.sh USER HISADDR UPTIME"


А вот и сами скрипты:
Не забудте дать права на исполнение!
vpn_up.sh
#!/bin/sh
if [ `mysql -uvpn -pvpn vpn -e "SELECT * FROM users WHERE nick='$1'"`="" ]
then
mysql -uvpn -pvpn vpn -e "INSERT into users (id, ip, nick, date, time, online) Values('Null', '$2', '$1', '`date -j +%F`', '`date -j +%T`', '1')"
else
mysql -uvpn -pvpn vpn -e "UPDATE users SET online='1', date='`date -j +%F`', time='`date -j +%T`', ip='$2' WHERE nick='$1'"
fi


vpn_down.sh
#!/bin/sh
mysql -uvpn -pvpn vpn -e "INSERT into sessions (id, ip, nick, date, time, uptime) Values('Null', '$2', '$1', '`date -j +%F`'
mysql -uvpn -pvpn vpn -e "UPDATE users SET online='0' WHERE nick='$1'"


Вот так мы заполучили все данные о сессиях (логин, выданый ип, время окончания сессии, длительность сессии) + табличку мониторинга пользователей. Все пользователи заводятся в базе автоматом, потом достаточно лишь заполнить ФИО «username» к логину пользователя «nick».

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

ЗЫ. Сильно ногами не пинать, любая конструктивная критика только приветствуется.

Организация коллекции изображений на основании данных EXIF. Пример на C#

Когда на жестком диске лежит около 10 ГБ отснятых разными аппаратами цифровых фотографий, разложить все это по полочкам не так уж просто.
Конечно, наверняка существуют платные и бесплатные приложения, помогающие разложить фотографии по папкам на основании данных о дате съемки, но для моих требований оказалось проще написать небольшую консольную программу на C#, почти скрипт.

Исходил из следующего:
1. Все фотографии разложены в папки по годам и месяцам (попытки навести порядок предпринимались неоднократно). Необходимо чтобы структура папок была сохранена.
2. Фотографии в папках некорректно отсортированы, т.к. снимал двумя телефонами и двумя фотоаппаратами, у каждого свой формат именования файла. Необходимо переименовать файлы так, чтобы сортировка по имени была сразу же сортировкой по дате, камере. Для надежности, сохранить старое имя файла.

Таким образом, нужно чтобы, файл, например, D:\Pictures\2008-03\11032008.jpg был скопирован в D:\Pictures New\2008-03\20080311 08.26.37 Nokia 5800 Xpres 11032008.jpg

А старую папку пожму архиватором в архив.

Оказалось, что в .NET 3.5 есть удобные классы для чтения метаданных из файла.

В итоге, за небольшое время получается такой код:
Читать дальше →

Пишем модуль ядра Линукс

Думаю каждый начинающий разработчик ядра Линукс мечтает написать свой модуль ядра. В этой статье я постараюсь объяснить как это сделать максимально просто, оставив все хитрые приемы на потом.
Поехали!

Базонезависимый код и C++

Появилась значит такая задача — получить код, который можно загружать по любому адрусу в памяти при минимальных ограничениях (юзание классов, аналоги операторов new и delete, доступ к WinAPI, COM, и т.п...)
Соответственно основные требования к требуемой программе — загружать WinAPI функции динамически через LoadLibrary (а саму LoadLibrary получить другим методом), никаких глобальных и статических переменных, строк и т.п.

Первая задача — получить адрес адрес Kernel32.dll, затем получить адреса самых важных функций:
// Стандартный метод получить хэндл Kernel32.dll
inline HMODULE GetKernel32(void)
{
__asm
{
mov eax,dword ptr fs:[30h]
mov eax,dword ptr [eax+0ch]
mov esi,dword ptr [eax+1ch]
lodsd
mov eax,dword ptr [eax+08h]
}
}
//-------------------------------------------------
// По хэшу функции и хэндлу модуля получаем адрес функции
//-------------------------------------------------
LPVOID GetProcAddressEx(HMODULE hModule, DWORD dwProcNameHash)
{
PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)
((char*)hModule + ((PIMAGE_DOS_HEADER)hModule)->e_lfanew +
sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
PIMAGE_EXPORT_DIRECTORY ped = (IMAGE_EXPORT_DIRECTORY*)RVATOVA(hModule,
poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD *pdwNamePtr = (DWORD*)RVATOVA(hModule, ped->AddressOfNames);
WORD *pwOrdinalPtr = (WORD*)RVATOVA(hModule, ped->AddressOfNameOrdinals);
DWORD *pAddrTable = (DWORD*)RVATOVA(hModule, ped->AddressOfFunctions);
int nOrdinal = -1;
unsigned int i;
for (i = 0; i < ped->NumberOfNames; i++, pdwNamePtr++, pwOrdinalPtr++, pAddrTable++)
{
char *s = (char*)RVATOVA(hModule, *pdwNamePtr);
if (CalcHash(s) == dwProcNameHash)
{
nOrdinal = *pwOrdinalPtr;
break;
}
}
pAddrTable = (DWORD*)RVATOVA(hModule, ped->AddressOfFunctions);
if (i == ped->NumberOfNames || nOrdinal<0) return 0;
DWORD dwRVA = pAddrTable[nOrdinal];
DWORD ret = (DWORD)RVATOVA(hModule, dwRVA);
return (LPVOID)ret;
}

//--------------------------------------------------
class BaseMain
{
public:
HMODULE hKernel;
HMODULE (WINAPI *pfLoadLibraryA)(LPCSTR lpLibFileName);
FARPROC (WINAPI *pfGetProcAddress)(HMODULE hModule,LPCSTR lpProcName);
VOID (WINAPI *pfExitProcess)(UINT uExitCode);
// Функции для работы с памятью
HANDLE hHeap;
HANDLE (WINAPI *pfHeapCreate)(DWORD flOptions,DWORD dwInitialSize,DWORD dwMaximumSize);
//...............................
System::Std::RFolder *Root;
public:
void Init();
void* Malloc(size_t size);
void Free(void *mem);
void Memset(void *mem,UCHAR val,size_t size);

};
void BaseMain::Init()
{
hKernel = GetKernel32();
void **p = (void**)&pfLoadLibraryA;
*p = GetProcAddressEx(hKernel,CalcHash("LoadLibraryA"));
p = (void**)&pfGetProcAddress;
*p = GetProcAddressEx(hKernel,CalcHash("GetProcAddress"));
// ..... Тут получаем адреса других функций....
}

#define PMAIN ((System::Main::BaseMain*)this->pMain)



Адреса загружаемых из DLL функций мы поместили в класс BaseMain. Сам этот класс можно поместить на стеке в главной функции (EntryPoint) программы:

void MyMain()
{
System::Main::BaseMain main;
main.Init();
........
main.pfExitProcess(0); // вместо ExitProcess(0); , т.к. программа скомпилирована без RTL
}



Теперь необходимо разобраться с памятью — т.к. глобальные переменные юзать нельзя, то у каждого класса, которому необходим доступ к WinAPI или другим функциям добавим поле void *pMain, которое будет указателем на созданный объект BaseMain:

class RClass
{
public:
void *pMain;
public:
//..........................
RClass* Init0(void *p){pMain=p;/*...*/}
};

void MyMain()
{
System::Main::BaseMain main;
main.Init();
RClass rclass;
rclass.Init0(&main);
//..................



Допустим даже все используемые классы будут унаследованы от RClass. Тогда использование функций BaseMain будет следующим:

// PMAIN у нас определено как #define PMAIN ((System::Main::BaseMain*)this->pMain)

void RClass::Func()
{
void *p = PMAIN->Malloc(100); // Вместо malloc
PMAIN->pfHeapAlloc(...); // Или любая функция, загруженная в BaseMain
}



Следующая важная задача — реализация аналога оператора new (чтобы у классов вызывался конструктор). Если просто написать MyClass cls = (MyClass*)PMAIN->Malloc(sizeof(MyClass)), то ничего хорошего из этого не выйдет, т.к. даже если нам не нужно вызывать конструктор класса, таблица виртуальных методов не будет заполнена и возможны вылеты там где не ожидаем. Поэтому реализуем функцию MyNew():

// Переопределяем оператор new(p) Class;
void * operator new(size_t size,void *p)
{
return p;
}
template T* MyNew(void *pMain)
{
void *p = ((System::Main::BaseMain*)pMain)->Malloc(sizeof(T));
T* t = new(p) T; // тут не будет выделена память для t (используется p), но будет вызван конструктор
t->Init0(pMain); // также инициализируем pMain в классе
return t;
}



Таким образом мы получили основной функционал для написания базонезависимого кода. Для удаления константных строк можно использовать скрипты обработки cpp файлов (которые заменяют строки вида "String" на код strings->GetString(143) // 143 - StringID ).

Полученный exe файл обладает минимальным размером (16 кб, учитывая что выравнивание секций по 4 кб), не импортирует никаких DLL (таблица импорта абсолютно пустая), секция данных также не содержит никакой информации.

Сделай сам. Программа «Бинауральные ритмы»

По мотивам сего топика

Сделал на скорую руку программку на LabView. (приколитесь, там все супер сложные программы виртуальных приборов можно делать на скорую руку!). Программа генерит два синусоидальных сигнала и передает их на два динамика(наушника). Можно изменить основную частоту сигнала и разность частот для левого и правого динамиков.

Вид программы
image

Структурная схема программы
image
пояснение для варианта False в структуре case
image

Скачать exe файл программы
Если у вас есть LabView, то вы можете самостоятельно скомпилировать свой вариант проги скачав vi проект
Кто заинтересуется будьте внимательны! Это опасно для здоровья.

Сам я ощутить эффект от прослушивания данной «музыки» не смог (возможно) из-за отсутствия хороших наушников.
Пока для меня остается открытым вопрос:
Как обычная музыка может создавать бинауральный эффект? Ведь это далеко не монотонный синусоидальный или еще какой сигнал.

PHP: работа с реплицированными mysql-серверами

Этот топик основан на советах, полученных от русского сообщества Zendframework и поисков по мануалам php.

Появилась достаточно интересная задача: в наличии два реплицированных сервера mysql: master и slave. Изменения на сервере master копируются в slave. Необходимо правильно организовать работу с базой данных, чтобы для программиста ее использование осталось максимально прозрачным (например, текущие интерфейсы классов библиотеки Zend не изменились), а разные типы запросов попадали на разные сервера.

Имеется в виду, что изменения данных (например, update) должны вестись с сервером master, а выборка (например, select) с сервера slave.
Читать дальше →

«Ручная» сортировка в SQL запросе

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

Речь пойдет о получении выборки из таблицы MySQL, отсортированной по какому-либо критерию (не обязательно по возрастанию или убыванию), информация о котором отсутствует в базе данных.
Читать дальше →

Тонкости компиляции внешних версий ALSA под Linux ядра.

Случилось недавно знаковое событие в мире потребительского звука под Linux — разработчики из ALSA исследовали предоставленый Creative код и написали-таки пусть нестабильный, пусть тестовый, но нативный и свободный от проприетарного кода честный модуль для звука Creative X-Fi под Linux.
(Доступный пока только в unstable ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/alsa-driver-unstable-snapshot.tar.gz)
Мне, как счастливому обладателю дома такой карты (так вышло) это была как манна небесная, наконец-то нормальный ЗВУК дома, там где он нужен больше всего, вместо напаянной на плату шуршалки.
Исходники скачаны, поддержка ALSA в ядре выключена (это обязательное требование для сборки внешних драйверов ALSA), исходники собраны, модули инсталлированы.

при загрузке модуля snd.ko получаем:
snd: Unknown symbol unregister_sound_special
snd: Unknown symbol register_sound_special
Или, при попытке загрузить сам модуль snd-ctxfi.ko, эти ошибки первыми, плюс простыню ошибок уже неизвестных символов из snd.ko который не загрузился, что естественно.

Читать дальше →

Новый проект «Пишем-Вместе.Ру»

image

Предлагаем Вашему вниманию новый стартап. «Пишем вместе» (www.pishem-vmeste.ru) — первый и пока единственный проект подобного рода на просторах Рунета. По сути, это не просто развлекательный ресурс, но и значимый социальный эксперимент.

Несколько слов о том, как возникла идея.

Мы неоднократно поражались творческим порывам пользователей интернета, читая красноречивые отзывы на туристических сайтах, живописные зарисовки о жизни и чувствах в блогах, здравые и абсолютно профессиональные рассуждения на специальных форумах и много-много другой информации, создаваемой посетителями различных ресурсов. Всегда в голову приходила мысль – насколько талантлив наш народ, и как этот талант иногда скрывается. При этом нужно отметить, что пользователи пишут свои заметки и более масштабные эпистолярные произведения совсем бескорыстно, просто самовыражаясь в слове. Так появилась идея объединить таких «писателей» рунета в рамках одного проекта, в рамках одного жанра, в рамках круга талантливых людей и интересных идей. Объединить – с целью создать масштабное, захватывающее художественное произведение.

Как мы решили эту задачу?

Мы сделали удобный инструмент для написания первой коллективной книги Рунета. «Читатели» видят просто книгу, удобную электронную книгу, читают единую историю в этой книге, и не замечают, где заканчивается отрывок одного автора и начинается отрывок другого. Всё – как в самой настоящей книги: содержание, главы, тексты, … скоро будут и картинки.

А какова же роль «писателей»? «Писатели» могут вставить свой собственный отрывок в любую часть нашей общей книги. Как только книга начнёт наполняться новыми сюжетными линиями, писатели получат уникальную возможность – редактировать мысли друг друга и дополнять свои идеи визуальными образами (картинками, фотографиями, рисунками).

Вы скажете, что где-то видели нечто подобное…

Да, возможно, это и так. Мы сами наблюдали такие начинания на различных форумах, и «В контакте». Они были весьма успешны в плане заинтересованности пользователей. Это ещё раз доказывает потребность людей в самовыражении. Но не было подходящего инструмента, и опыт не стал массовым. Форум – это форум, в нем отсутствует главное – ощущение целостности художественного произведения. Мы преодолеваем это и «заточены» под настоящую книгу.

Wordpress – скрипт наполнения контентом

Дано:



Вы предложили клиенту использовать в качестве CMS – Wordpress и создали сайт используя его. Но клиент рад бы забивать посты руками, вот только обучать сотрудников работать в Wordpress ему не в кайф. Поэтому он предлагает сделать скрипт наполнения контентом, который будет брать посты из Excel-файла и в зависимости от того, изменились ли они или добавились, производить с ними нужные действия на сайте.

Сам файл будет состоять из трех полей:

  • категории (через запятую ID категорий);
  • название поста;
  • контент поста;
  • теги (через запятую);
  • уникальный идентификатор поста (внешний по отношению к Wordpress)


Решение:



Создаем в корневой директории сайта файлик (к примеру postposts.php), и пишем в его начале строки:

define(’WP_USE_THEMES’, false); // отключаем поддержку тем

require(’./wp-blog-header.php’); // подключаем blog-header в котором у нас есть штатный API Wordpress


Теперь сохраняем наш Excel-файл с постами в корневой директории сайта (как к примеру posts.txt) из Excel как текстовый файл с разделителем табуляцией. Открываем его и сохраняем в UTF-8 без BOM.

Теперь пишем код который открывает файл и разбивает его на строки. Я делаю это вот так:

$f = file_get_contents(”posts.txt”); // читаем контент файла

$f = explode(”\t \r\n”,$f); // разбиваем его на строки


Техническое отступление:



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


Теперь у нас есть массив $f который можно прочитать в цикле foreach к примеру вот так:

foreach ($f as $k=>$v)

{


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

$v = explode(”\t”,$v); // получаем массив полей
$categories = explode(”,”,$v[0]); // получаем массив ID категорий (INT)
$title = trim($v[1]); // название поста
$content = trim($v[2]); // контент поста
$tags = explode(”,”,$v[3]); // получаем массив тегов
$pid = intval($v[4]); // получаем уникальный идентификатор поста (внутренний по отношению к нашему файлу)


Теперь у нас есть считанные данные поста которые необходимо внести в базу данных Wordpress. Естественно рекомендую для этого использовать штатный Wordpress-API, не зря же мы его подключали в начале файла :)
Мы будем использовать функции wp_insert_post() и wp_update_post(). К примеру вот так:

if ($pid>0) // если у нас считался корректный ID
{
	$sql = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'unique_id' AND meta_value='$pid'"; // выбираем нужный нам пост по его meta-полю unique_id
	$ID = $wpdb->get_results($sql); // получаем результат запроса
	$ID = intval($ID[0]->post_id); // получаем Wordpress-post_id (ID нашего поста в Wordpress)
	if ($ID>0) // если он выбрался
	{
		//создаем массив для wp_update_post
		$my_post = array(
			'ID'=> $ID,//ID поста
			'post_category' => $categories, // категории
			'post_content' => str_replace("\r\n","<br />",$content), // контент
			'post_date' =>  date ("Y-m-d H:i:s"), // дата внесения поста
			'post_status' => 'publish', // статус поста
			'post_title' => $title, // название
			'post_type' => 'post', // тип (page или post)
			'tags_input' => $tags, // теги
			'post_author' => 1);// ID автора поста
		$post_id = wp_update_post( $my_post ); // вызываем функцию обновления поста которая вернет нам ID поста.
		echo $pid." - existing post update<br />"; // выводим незатейливый лог :)
	}
	else // если поста еще нет в базе и он не выбрался
	{
		$my_post = array(
			'post_category' => $categories, // категории
			'post_content' => str_replace("\r\n","<br />",$content), // контент
			'post_date' =>  date ("Y-m-d H:i:s"), // дата
			'post_status' => 'publish', // статус
			'post_title' => $title, // название
			'post_type' => 'post', // тип записи
			'tags_input' => $tags, // теги
			'post_author' => 1); // ID автора
		$post_id = wp_insert_post( $my_post ); // функция добавления поста
		add_post_meta($post_id, "unique_id", $pid); // добавляем meta-поле unique_id которое понадобится нам для ориентации в наших постах из Excel-файла
		echo $pid." - insert new post<br />"; // выводим в лог
	}
}

Теперь закрываем наш foreach – } и на этом заканчивается наш скрипт.

Выводы



Мы сделали удобную утилиту для Wordpress которую вполне можно оформить как плагин и выложить на wordpress.org. Надеюсь вам это пригодилось :)

Ускоряем работу игр под Wine в Linux

Даже «мегастрашные бородатые дядьки», коими часто представляют пользователей *nix-систем иногда хотят поиграть в компьютерные игры, при этом не ограничивая себя стандартными играми. Каждый пользователь linux знает о существовании Wine, помогающего запускать win-приложения, в том числе игры. А так же они знают о том, что wine далеко до совершенства.
Я хочу помочь решить часть проблем wine, а именно проблемы подвисших приложений, низкий FPS и проблемы отказа переключения по ctrl+tab.

Читать дальше →

*nix'овые команды в консоли Windows

Я работаю инжеНегром в одной большой китайской компании и почти постоянно сижу в консолях различных ОС. Чаще всего это SLES, но бывают и Solaris, и даже иногда HPUX.

Но на корпоративных буках стоит только Windows. А после недели\двух в консоли на *nix виндовая консоль часто ругается на то, что не знает команд ls, ifconifg, man и т.д.

Конечно, есть аналоги под вин, есть cygwin и много чего. Однако для меня как правило, остаточно аналогов, нативных под виндой — dir, ipconfig etc. Опять же, бывает недостаточно прав на установку ПО, либо это явно запрещено.

Я нашел для себя простой выход
Читать дальше →

InTV Tuner — Просмотр InTV.ru без рекламы, с удобной навигацией и поиском, фулскрин и без проблем с энергосбережением

Итак… безгеморойный (суть удобный и без рекламы) просмотр видео с ресурса intv.ru тема в рунете весьма популярная. Однако до сих пор никто не озаботился сделать сей процесс по-настоящему удобным. Чтобы в этом убедиться, достаточно погуглить по «intv без рекламы» и уныло созерцать результаты, мало относящиеся к делу, например, вот этот пост на хабре с привлечением каких-то сторонних тулзов типа VLC или какие-то левые букмарклеты для firefox, изобретенные ленивыми линухоидами :) Но теперь все в прошлом, потому что появилось по-настоящему удобное решение (и да, пока только под винды).

image

Что уже есть

— Просмотр видео «в один клик»
— Никакой рекламы, ни текстовой. никаких внезапных прерываний видео рекламой
— Навигация по жанрам
— Поиск фильмов
— Автоматическое отключение скринсейвера и энергосбережения, ваш комп теперь не уйдет в зелень и монитор не выключится, если вы давно не трогали мышку ;)
— Возможность просмотра видео на полный экран без всяких мешающих панелей и логотипов
— Возможность скачать фильм по прямой ссылке
— Бесплатно и фриварно

Что скоро будет

— Добавятся еще сайты с фильмами
— Еще более улучшится навигация
— Видео можно будет автоматически сохранять при просмотре

Где взять

http://intv-tuner.blogspot.com/

Где обсудить

http://forum.ru-board.com/topic.cgi?forum=5&topic=30782

Тайм-менеджмент и коворкинг. Радикальное решение вопроса.

Хочу поделиться интересной идеей успешной организации коворкинга для отдельно взятого человека. Для меня сработало «на ура», значит, наверное, и другим пригодится. Если вы одиночка в работе, то это то, что доктор прописал. Способ очень дешевый и оригинальный.
Читать дальше →

Спам (и антиспам) → Утилита для настройки OpenDNS

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

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

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

Саму утилиту можно скачать тут