Archive for the ‘ Мозг ’ Category

Ярлык в области уведомлений

Сегодня я всего лишь хочу привлечь внимание к одной проблеме — различающихся способов сворачивания программ в область уведомлений.

Недавно я поспорил с другом из-за µTorrent - я всегда настраиваю его так, чтобы при нажатии кнопки «Свернуть» он сворачивался в область уведомлений и «Закрыть» — закрывался. По мнению друга, логичнее сделать, чтобы после нажатия «Свернуть» программа сворачивалась в панель задач, «Закрыть» — в область уведомлений, а закрывалась при выборе в меню пункта «Выход».

Приведу свою аргументацию, она довольно проста. Когда вы пишете программу, и в ней есть код, который закрывает дочернее окно, то закрывается именно это окно. Если же в коде обозначено, что надо закрыть главное окно, то завершает работу вся программа. И если уже задумано так, что по «Закрыть» закрывается вся программа, то зачем переназначать действие этой кнопки, это ведь путает конечного пользователя. От таких переназначений и вся неразбериха.

Я решил обратиться к официальному источнику, и нашел Руководство по созданию пользовательских интерфейсов для Windows. Внимательно посмотрев, что там написано про область уведомлений, нашел следующее на странице 792:

Minimizing programs to the notification area
Note: Minimizing program windows to the notification area is no longer recommended for Windows 7. Use regular taskbar buttons instead. Your program may support both mechanisms for backward compatibility.

• To reduce taskbar clutter, consider providing the ability to minimize programs to the notification area only if all of the following apply:
- The program can have only a single instance.
- The program is run for an extended period of time.
- The icon shows status.
- The icon can be a notification source.
- Doing so is optional and users must opt in.
• Use the Minimize button on the application’s title bar, not the Close button.

В переводе получается примерно так:

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

• Для борьбы с засорением панели задач, следует рассмотреть вопрос о предоставлении возможности минимизации программы в область уведомлений, только если выполняются следующие условия:
- Программа может иметь только один экземпляр.
- Программа выполняется в течение длительного периода времени.
- Значок показывает статус.
- Значок может быть источником уведомлений.
- Это не является обязательным и пользователи должны иметь возможность настройки
• Используйте кнопку Свернуть в строке заголовка приложения, а не кнопку Закрыть.

Microsoft даже не рекомендует, а прописывает как должное «Используйте кнопку Свернуть в строке заголовка приложения, а не кнопку Закрыть».

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

Автозамена ключей Nod32 (запись #2)

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

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

function RussianToUnicode(S: String): String;
var
  Wrd: Word;
  pW,pR: PWord;
  len: integer;
begin
  pW:=@S[1];
  len:=Length(S);
  SetLength(Result,len);
  pR:=@Result[1];
  while Len<>0 do
  begin
    Wrd:=pW^;
    case Wrd of
      $C0..$DF,$E0..$FF:pR^:=Wrd+50;
      else pR^:=Wrd;
    end;
    inc(pW);
    inc(pR);
    dec(Len);
  end;
end;

Укажем константы и переменные:

const
  serv = 'your-server.com';
  pcid = '75434347623';
var
  can: boolean;
  keynod, hashnod: string;

На форму кинем TButton и TIdHttp. Для TButton в событии OnClick пропишем следующее:

// получаем ключ (ну или хотя бы пытаемся)
try
  if (can) then temp:=RussianToUnicode(idHTTP.get('http://'+server+'/key4nod.php?type=2&pcid='+pcid));
except
  // в случае ошибки - снимаем флажок
  can:=false;
end;
// если нет новых ключей, снимаем флажок
if (temp = 'Нет новых ключей') then can:=false;
if (can) then keynod:=temp;   // запоминаем ключ
// получаем хеш пароля (ну вообще это не хеш, а видимо зашифрованный пароль
// и сохраненный в бинарном виде - главное, что на разных компах этот "хеш"
// не меняется (по крайней мере на проверенных мной трех компах)
try
  if (can) then temp:=RussianToUnicode(idHTTP.get('http://'+server+'/key4nod.php?type=5&pcid='+pcid+'&key='+keynod));
except
  // надоели уже проверки, но что же поделать...
  can:=false;
end;
// бинарный код получили - можно продолжать
if (can) then hashnod:=temp;
if (can) then
begin
  codes:=TStringList.Create;
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  i:=0;
  temp:='';
  while Pos(' ', hashnod)>0 do
  begin
    temp:=Copy(hashnod, 1, Pos(' ', hashnod)-1);
    Delete(hashnod, 1, Pos(' ', hashnod));
    Buf[i]:=StrToInt(temp);
    inc(i);
  end;
  // и пытаемся установить ключ в систему (должно быть выключено SelfDefendece)
  try
    Reg.OpenKey('SOFTWARE\ESET\ESET Security\CurrentVersion\Plugins\01000400\Profiles\@My profile', True);
    Reg.WriteString('Username', keynod);
    Reg.WriteBinaryData('Password', Buf, SizeOf(Buf));
    Reg.CloseKey;
  Reg.Free;
  except
    ShowMessage('Ошибка при установке ключа');
  end;
  codes.Destroy;
end;

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

Да, чуть не забыл о самом главном. У антивируса должен быть снять флажок напротив пункта «Self-Defendece» так как иначе он будет защищать себя и не даст заменить свои настройки в реестре.

Автозамена ключей Nod32 (запись #0)

Добрый день. Это нулевая запись из трех, а может и больше, про автоматическую смену ключей для антивируса Nod32. С чего все началось? Мои родители — индивидуальные предприниматели, у них есть есть магазин, недавно там была проведена полная автоматизация — поставлен компьютер со специальным программным обеспечением и оборудованием (считыватель штрих-кода, кассовый аппарат), плюс есть офис. Понятное дело, как самый знаток в семье, я заведую всеми компьютерными делами. То есть, несколько компьютеров дома, объединенных в сеть с помощью маршрутизатора ASUS RT-N10, офисный и магазинный компьютеры — все на мне. Ясное дело, на них нужны антивирусы. Для этого дела покупается 2 выпуска журнала ComputerBild в месяц — и ключи распределяются, благодаря чему получается неплохая экономия. Так вот, раньше-то я бегал и устанавливал эти ключи в пределах одной квартиры, а теперь мне нужно ездить каждый месяц в торговый центр и офис просто чтобы обновить ключ… Не удивительно что я решил не тратить на это 2 часа, а написать программу, которая бы сама забирала ключ с моего сервера и устанавливала на компьютер, на котором она запущена. Сделал снимок реестра с помощью RegShot, установил другой ключ, сделал второй снимок — и обнаружил, что настройки у антивируса Nod32 хранятся тут:

HKEY_LOCAL_MACHINE\SOFTWARE\ESET\ESET Security\CurrentVersion\Plugins\01000400\Profiles\@My profile

Соответственно, имя пользователя хранится в параметре стокового типа Username, а пароль — бинарного типа Password. «Ага» — подумал я, и решил, что на сервере будет храниться имя пользователя и пароль именно в таком бинарном виде, чтобы было проще записывать на конечном компьютере.

В этой записи я рассказываю о программе, которая позволяет считать и скопировать в буфер пароль (так сказать, начинаю с самого простого, хотя ее я написал уже после основной — клиентской). Итак, начнем.

В разделе uses подключаем модули TRegistry (для работы с реестром) и ClipBrd (для работы с буфером обмена). На форму кидаем 2 кнопки TButton и поле ввода TMemo. На кнопках пишем «Найти» и «В буфер». в Memo1 в параметре Lines пишем «Здесь будет отображен результат работы» вместо «Memo_num» и устанавливаем атрибут ReadOnly в True чтобы нельзя было случайно удалить данные. Должно получиться что-то вроде этого:Набросок формы

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

procedure TForm1.Button1Click(Sender: TObject);
var
  Reg: TRegistry;
  Buf: array[0..20] of Byte;
  c,i: integer;
begin
  FillChar(Buf, SizeOf(Buf), 0);
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  try
    Reg.OpenKey('SOFTWARE\ESET\ESET Security\CurrentVersion\Plugins\01000400\Profiles\@My profile', True);
    c := (Reg.ReadBinaryData('Password', Buf, SizeOf(Buf)));
    Memo1.Lines.Strings[0]:=InttoStr(c)+' байт считано: ';
    for i := 0 to c - 1 do
      Memo1.Text:=Memo1.Text+InttoStr(Buf[i])+' ';
    Reg.CloseKey;
  finally
    Reg.Free;
  end;
end;

Это означает, что сначала мы инициализируем переменную, затем переходим в раздел «HKEY_LOCAL_MACHINE» и идем туда, куда нам нужно, считываем оттуда переменную и выводим ее в поле.

Для кнопки «В буфер» пишем всего одну строку:

Clipboard.SetTextBuf(PChar(Memo1.Lines.Strings[1]));

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

ЧПУ

Начал разработку CashFinder и решил поделиться с вами, дорогие читатели, скриптом ЧПУ. В моем варианте он позволяет создавать статические и динамические страницы, просто добавляя их адрес, название и текст или путь к модулю в соответствующие таблицы базы данных. Также можно получать параметры из адреса, к примеру, id просматриваемой новости (http://ваш_сайт.ру/news/1/)

Итак, для начала в файле .htaccess нужно прописать:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]

Затем в файле index.php пишем:

$page_url = $_SERVER['REQUEST_URI'];
$page_url = trim($page_url, '/');
$page_url = strtolower($page_url);
if (!$page_url) $page_url = 'index';
$params = explode('/', $page_url);
$i = count($params);
while ($i > 0)
{
  $query = mysql_query("SELECT * FROM `module` WHERE `url`='".$page_url."'");
  if (mysql_num_rows($query))
  {
    $page_name = mysql_result($query, 0, 'name');
    $page_file = mysql_result($query, 0, 'file');
    break;
  }
  else
  {
    $query = mysql_query("SELECT * FROM `page` WHERE `url`='".$page_url."'");
    if (mysql_num_rows($query))
    {
      $page_name = mysql_result($query, 0, 'name');
      $page_text = nl2br(mysql_result($query, 0, 'text'));
      break;
    }
    else
    {
      $page_url = str_replace('/'.$params[$i-1], '', $page_url);
      $page_par = $params[$i];
    }
  }
  $i--;
}
$page_url = implode("/", $params);
if (!$page_name)
{
  $page_text = 'Ошибка 404' ;
  $page_name = 'Страница не найдена';
}

Итак, сначала получаем адрес страницы и записываем в переменную $page_url. Затем убираем слеши и приводим все к нижнему регистру, не забыв, что если запрос пустой, значит это — главная страница.

Создаем массив с отдельными частями адреса и начинаем искать в БД его примерно по такому принципу: к примеру, адрес страницы user/edit/34. Сначала в базе ищется полностью адрес. Если не найден, удаляется последний параметр и $page_url становится равным user/edit. И так ищем пока что-нибудь не найдем (выход из цикла с помощью break) или пока не перепробуем все варианты.

Если ничего не найдено, то записываем в необходимые переменные информацию об ошибке, если найдено — то обрабатываем, как нам нужно и выводим (в зависимости от того, найдена ли страница — выводим содержимое или файл модуля — инклудим)

Вот и все, человеко-понятный урл готов!

Менталитет россиян

Ехал в воскресенье в другой город и едущие навстречу машины натолкнули на одну очень простую мысль: «Пиратство в России будет искоренено только тогда, когда мы перестанем предупреждать друг друга о засевшем в засаде ГАИшнике. То есть никогда». Трудно не согласиться?

Еще порадовало название фитнес-центра «Бобрики». Но это все просто вступление из-за того, что даже не знаю о чем написать.

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

Собираюсь закрыть ВирВин и, переконвертировав пользователей, открыть систему тизерной рекламы с выгодной реферальной системой, минимальной комиссией и высокими ценами.

Между прочим, некий разработчик имеет наглость утверждать, что его ‘мощный’ скрипт *** работает быстрее и лучше, чем мой. А сам тем временем использует print вместо echo и mysql_query вместо mysql_unbuffered_query, из чего следует, что он работает медленнее и использует больше памяти.

Geo IP конвертер

Добрый день! Хоть я и очень запарился, делая PinkContext и времени у меня уже нет, я все же собрался с мыслями, сел и написал этот пост.

Как я и обещал, сегодня я пишу о том, как сконвертировать GeoIP базу от MaxMind и как ей потом пользоваться. Итак, сразу к делу, вот листинг конвертера:

require_once("config.php");
$file = fopen("GeoIPCountryWhois.csv", "r");
flock($file, 1);
$i = 0;
while (!feof($file))
{
	$mass = fgetcsv($file, 1024);
	$begin[$i] = $mass[2];
	$end[$i] = $mass[3];
	$code[$i] = $mass[4];
	$i++;
}
$geoquery = mysql_query("SELECT * FROM `geoip`");
$c = mysql_num_rows($geoquery);
for ($i = $c; > count($begin); $i++)
{
	mysql_query("INSERT INTO `geoip` VALUES ('".$begin[$i]."', '".$end[$i]."', '".$code[$i]."')");
}
flock($file, 3);
fclose($file);
if ($i == count($begin)) echo "Завершено";

А теперь опишу как же все это работает. Во-первых, подключаемся к базе данных, используя общий файл настроек — config.php. Затем открываем файл базы и пока не дойдем до конца считываем его циклом в массив. После этого смотрим, сколько уже записей в базе (на случай, если с первого раза база не сконвертировалась полностью из-за ограничений на время исполнения) и начиная с места последней записи вставляем новые значения.

В итоге, когда скрипт полностью завершит свою работу, он выведет «Завершено».

Как же использовать эту базу? Для определения страны с ее помощью я сделал небольшую функцию:

function geoip($ip)
{
$params = explode(".", $ip);
$adr = 16777216*$params[0] + 65536*$params[1] + 256*$params[2] + $params[3];
$query = mysql_query("SELECT * FROM `geoip` WHERE '".$adr."' BETWEEN `begin` AND `end` LIMIT 1");
if (mysql_num_rows($query))	$code = mysql_result($query, 0, "code"); else $code = "";
return $code;
}

Как видно, ей передается IP адрес и на выходе она возвращает код страны (если ничего не найдено результат — пустая строка). Вот и все, база готова  использованию…

Подошел к концу десятый пост моего блога. Желаю вам и себе удачи во всех начинаниях!

P.S. После пятидесятой записи всех ждет полезный сюрприз

PinkContext (запись #1)

Вот и запущена в тестовом режиме система контекстной рекламы с оплатой за показы PinkContext. На данный момент открыта регистрация только вебмастеров.

Сегодня я хочу написать о том, как я переконвертировал пользователей из проекта 7pop в PinkContext.

Для начала в файле конвертера делается запрос в базу данных с пользователями и выбираются оттуда все с положительным балансом (предварительно конечно подключив файлы с настройками подключения к БД):

$query = mysql_query("SELECT * FROM `users` WHERE `balans` != 0 ORDER BY `id`");

Затем циклом все пользователи записываются в новую базу данных:

for ($i = 0; < mysql_num_rows($query); $i++)

А вот дальше начинаются чудеса. Нужно оповестить каждого пользователя о том, что открыта новая система и что он автоматически в ней зарегистрирован с его данными из старой системы. «А вдруг он не помнит свои старые данные» — вот главная проблема. Значит нужно отправить ему его логин и пароль на электорнную почту. Как же узнать пароль, ведь он захеширован? Значит нужно создать новый. Вот как это сделал я:

$id = $_GET["id"];
$text = UrlDecode($_GET["text"]);
$title = UrlDecode($_GET["title"]);
$query = mysql_query("SELECT * FROM `user` WHERE `id` = '".$id."'");
if (!mysql_num_rows($query)) die('Пользователя с id '.$id.' не существует');
$login = mysql_result($query, 0, "login");
$email = mysql_result($query, 0, "email");
if (!$login) $login = $email;
if (preg_match('/%username%/', $text)) $text = preg_replace('/%username%/', $login, $text);
if (preg_match('/%password%/', $text))
{
  $password = RandStr(8);
  $text = preg_replace('/%password%/', $password, $text);
  $password = md5($password);
  $query = mysql_query("UPDATE `user` SET `pass` = '".$password."' WHERE `id` = '".$id."'");
}
$headers = 'Content-type: text/html; charset=utf-8 '.'\r\n';
$headers .= 'From: '.$site_mail.' '.'\r\n';
mail($email, $title, $text, $headers);

Что же этот скрипт делает? Для начала он забирает из основного модуля 3 переменных — id пользователя, которому нужно отправить сообщение, заголовок сообщения и текст сообщения. После этого лезет в БД и запрашивает данные выбранного пользователя, попутно проверяя наличие его в базе. В моем случае в предыдущей базе у пользователей не было ников, поэтому можно заходить и с помощью электронной почты и с помощью ника.

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

Вот функция для генерации случайной строки:

function RandStr($pass_len)
{
  $allchars = "abcdefghijklnmpqrstuvwxyzABCDEFGHIJKLNMPQRSTUVWXYZ123456789";
  $string = "";
  mt_srand ((double) microtime() * 1000000);
  for ($i = 0; $i < $pass_len; $i++)
  {
    $string .= $allchars{mt_rand (0,strlen($allchars))};
  }
  return $string;
}

А в следующий раз я напишу, как сконвертировать GeoIP базу от MaxMind в базу данных MySQL (так как такие вопросы иногда возникают у начинающих программистов)

PinkContext (запись #0)

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

Настройка отображения блока:Настройка отображения

Рекламный блок

А так выглядит контекстный блок, настроенный так, как показано выше.

Одним словом, с виду ничего особенного. Но внутри много интересного, как для владельцев площадок, так и для рекламодателей.

В скором времени состоится запуск системы и все увидите сами.

Вирвин — epic fail?

Сегодня я решил рассказать об опыте владения небольшой системой биржи трафика — «Вирвин». На этот проект меня воодушевил другой проект — Mr Bax — они придумали вирус-окошко, однако весь сайт, начиная от дизайна и заканчивая кодом, оставляет желать лучшего, именно поэтому я и решил заняться этим же форматом. Думаю, название VirWin вполне понятно — это сокращение от VirusWindow.

Затем я придумал еще пару форматов — UcozWindow (пользуется успехом) и LoadWindow. Чуть позже добавил тизерный формат и чтобы не скликивали накрутчики, все ссылки везде сделал с помощью div-ов.

Теперь по поводу затрат и доходов. Домен был куплен за 99 рублей у знакомого на хостинге Tramo, виртуальный сервер за все время работы — 400 рублей. Ну и 320 рублей — выплаты.

Много на что лил, но потом после convertit (могу дать инвайт) понял, что конвертируется только порно. В итоге слил всего 200 человек в выше указанную пп и получил одну подписку с двумя удачными ребиллами на сумму 58 рублей 63 копейки (потом юзер отписался). На скрытых фреймах заработал 5 долларов 50 центов. Еще заработал 10 рублей на реальном рекламодателе. Заработанные далее деньги были открытием и совершенной неожиданностью.

В пп microslon я сливал трафик на программу для просмотра фильмов в 3D. Конверт нулевой. И тут вдруг на тизерах с рекламы «Уникальная методика избавления от прыщей» получил 18 рублей 4 копейки. Но еще большей неожиданностью стала конвертация платных файловых архивов со StimulProfit — за 2 дня слива трафика (всего 50 человек в сутки) было отправлено 4 смс сообщения (общий доход с них составил 3 доллара 14 центов) — и это было не порно. Но удивительнее всего, что они были отправлены с Украины. Вот после такого и задумываешься, справедлива ли завышенная стоимость российского трафика по отношению стоимости трафика СНГ?

Подведем итоги: потрачено на сайт 499 рублей, потрачено на выплаты пользователям 320 рублей, получено 526 рублей 48 копеек. Результат — минус 292 рубля 52 копейки. Полученный опыт: защита от накрутчиков (система защиты трафика «Эдбака»).

Вывод: по моему мнению, Вирвин — крайне удачный опыт управления биржей трафика.

Осторожно, злая «Эдбака»

«Эдбака» наконец-то запущена, сбор ip идет в штатном режиме. Первые реальные тестирования показали, что ни один случайный пользователь не был заблокирован, 50% накрутчиков было отфильтровано. И это уже неплохие результаты. Тем более, что до конца недели этот показатель будет выведен до уровня 90%.

Внимание, если вы хотите попробовать «Эдбаку», то до 25 июля у вас есть возможность сделать это совершенно бесплатно! Не пугайтесь тарифных планов — скорее всего в ближайшее время тарифы будут пересмотрены в сторону удешевления.

Не боимся, регистрируемся и ставим защиту на свою биржу — от нее хуже не будет.

P.S. Кстати, сегодня система накрутки «Самариум» выпустила новую версию браузера, которая полностью эмулирует действия пользователя, например, пролистывает полосу прокрутки, а также умеет скликивать любые элементы страницы,будь то <a> — ссылка или <div> — слой (другие пока не умеют скликивать слои).