четверг, 4 февраля 2010 г.

13 полезных SQL-запросов к базе данных Wordpress

13 полезных SQL-запросов к базе данных Wordpress

Сейчас мы поговорим о наиболее полезных SQL-запросах к базе данных Wordpress. Эти запросы помогут вам сократить время, которое может быть затрачено на выполнение многих рутинных веще, как-то: смена имени автора для множества постов, смена какого-либо URL внутри поста и т.д.

Далее – шпаргалка из 13-ти наиболее полезных запросов.

1. Меняем значения Siteurl и Homeurl (необходимо при переезде на другой домен):

UPDATE wp_options SET option_value = replace(option_value, 'http://www.oldsiteurl.com', 'http://www.newsiteurl.com') WHERE option_name = 'home' OR option_name = 'siteurl';

2. Меняем значение GUID (необходимо все для того же):

UPDATE wp_posts SET guid = REPLACE (guid, 'http://www.oldsiteurl.com', 'http://www.newsiteurl.com');

3. Меняем значение URL внутри постов (без комментариев):

UPDATE wp_posts SET post_content = REPLACE (post_content, 'http://www.oldsiteurl.com', 'http://www.newsiteurl.com');

4. Меняем путь к картинкам (э… допустим, что вы перенесли все свои картинки в какую-нибудь CDN, типа Amazon CloudFront):

UPDATE wp_posts SET post_content = REPLACE (post_content, 'src="http://www.oldsiteurl.com', 'src="http://yourcdn.newsiteurl.com');

и

UPDATE wp_posts SET guid = REPLACE (guid, 'http://www.oldsiteurl.com', 'http://yourcdn.newsiteurl.com') WHERE post_type = 'attachment';

5. Обновляем метаинформацию постов (причины… те же, что у первых трех):

UPDATE wp_postmeta SET meta_value = REPLACE (meta_value, 'http://www.oldsiteurl.com','http://www.newsiteurl.com');

6. Меняем имя администратора по умолчанию (не всем же нравится просто «admin»):

UPDATE wp_users SET user_login = 'Your New Username' WHERE user_login = 'Admin';

7. Сбрасываем пароль (уже что-то полезное):

UPDATE wp_users SET user_pass = MD5( 'new_password' ) WHERE user_login = 'your-username';

8. Меняем автора поста с A на B:

UPDATE wp_posts SET post_author = 'new-author-id' WHERE post_author = 'old-author-id';

9. Удаляем старые версии постов:

DELETE a,b,c FROM wp_posts a
LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
WHERE a.post_type = 'revision';

10. Удаляем метаинформацию из поста (это нужно, например, чтоб удаленные плагины не засоряли БД и страницы своими останками):

DELETE FROM wp_postmeta WHERE meta_key = 'your-meta-key';

11. Делаем экспорт всех e-mail’ов наших любимых комментаторов без повторений:

SELECT DISTINCT comment_author_email FROM wp_comments;

12. Удаляем все пингбэки из комментариев:

DELETE FROM wp_comments WHERE comment_type = 'pingback';

13. Удаляем весь спам из комментариев:

DELETE FROM wp_comments WHERE comment_approved = 'spam';

14. Вычисляем неиспользуемые тэги (это либо бонус, либо авторы оригинальной статьи не умеют считать, либо что-то не так со мной):

SELECT * FROM wp_terms wt
INNER JOIN wp_term_taxonomy wtt ON wt.term_id=wtt.term_id
INNER JOIN wp_term_relationships wtr ON wtr.term_taxonomy_id=wtt.term_taxonomy_id
LEFT JOIN wp_posts wp ON wp.ID=wtr.object_id
WHERE taxonomy='post_tag'
AND ID IS null
AND NOT EXISTS(SELECT * From wp_terms wt2
INNER JOIN wp_term_taxonomy wtt2 ON wt2.term_id=wtt2.term_id WHERE wtt2.parent=wt.term_id) ORDER BY name;

Да, вы же не забыли сделать бэкап?!

понедельник, 1 февраля 2010 г.

jQuery и Google Maps API №3: Подборка плагинов

Сразу предупрежу, что представленные здесь плагины не расширяют функционал самого Google Maps API (что и понятно), но нужны для того, чтобы упростить интеграцию карт Google и привести JS-код к некоторому единообразию, если для разработки клиент-side части приложения используется jQuery.
Итак, сегодняшние герои:


  1. jmaps;

  2. googlemaps;

  3. jquery-googlemap

  4. Google Maps jQuery Plugin

О последнем, скорее всего, совсем скоро расскажу чуть подробнее.

ZfConf 2010

Спешу порадовать вас, немногочисленные мои читатели!
В конце марта 2010 г. в Санкт-Петербурге пройдет первая в России конференция по Zend Framework
На днях закончился прием тезисов по планируемым докладам. Примечательно, что в состав докладчиков вошли ведущие участники русскоязычного сообщества ZF, опытнейшие специалисты и лично один из создателей фрэймворка!
На данный момент уже открыта предварительная регистрация на конференцию (http://www.zfconf.ru/pre-registration.php)! Для решения ряда вопросов организаторам очень важно сейчас понять приблизительное количество человек, которые смогут посетить конференцию или каким-то иным образом принять участие в ней.
Каждый предстоящий доклад возможно обсудить на форуме ZF-сообщества. Ваше мнение очень важно для авторов!

Планируемые доклады:

Жизненный цикл предложений (proposals) в проекте Zend Framework
Александр Веремьев (Zend Technologies, Zend Framework Core команда)
http://zendframework.ru/forum/index.php?topic=2269.0

Zend_Search_Lucene в деталях
Александр Веремьев (Zend Technologies, Zend Framework Core команда)
http://zendframework.ru/forum/index.php?topic=2270.0

Zend Framework и производительность
Александр Махомет (создатель сообщества ZendFramework.ru)
http://zendframework.ru/forum/index.php?topic=2271.0

Zend Framework и MVC, «толстая» модель
Александр Стешенко (Norada Corporation, PHP-разработчик)
http://zendframework.ru/forum/index.php?topic=2272.0

ФотоСтрана.ru: Прототипирование с использованием ZF (история боевого применения Zend Framework в highload-проекте)
Леонид Жаворонков (ФотоСтрана.ru, тимлид)
http://zendframework.ru/forum/index.php?topic=2273.0

Использование очередей сообщений в повседневных проектах
Денис Баклыков (Обновление, веб-разработчик)
http://zendframework.ru/forum/index.php?topic=2274.0

Zend Framework и Doctrine
Степан Танасийчук (руководитель веб-студии stfalcon.com)
http://zendframework.ru/forum/index.php?topic=2275.0

Zend Framework и мультиязычность
Степан Танасийчук (руководитель веб-студии stfalcon.com)
http://zendframework.ru/forum/index.php?topic=2276.0

История проекта e-Штаб
Анатолий Ларин (e-Легион, веб-программист)
http://zendframework.ru/forum/index.php?topic=2277.0

Что нового несет нам Zend Framework 2.0?
Надежда Блинова (Wizartech, веб-программист), Георгий Туревич (Wizartech, ведущий веб-программист)
http://zendframework.ru/forum/index.php?topic=2278.0

Интеграция Zend Framework c Javascript-фрэймворками jQuery и Dojo Toolkit
Георгий Туревич (Wizartech, ведущий веб-программист)
http://zendframework.ru/forum/index.php?topic=2279.0

Смело обсуждайте доклады и регистрируйтесь (http://www.zfconf.ru/pre-registration.php)!

За последними новостями можно следить здесь:
1. RSS-канал: http://feeds.feedburner.com/zfconf
2. Twitter: @zfconf (http://twitter.com/zfconf)
3. Группа Вконтакте: http://vkontakte.ru/club14951507

К участию также приглашаются информационные и финансовые спонсоры.

четверг, 21 января 2010 г.

jQuery и Google Maps API №2: Добавляем в БД и на карту маркеры при помощи AJAX

jQuery и Google Maps API №2: Добавляем в БД и на карту маркеры при помощи AJAX

Итак, продолжаем наши мытарства вместе с jQuery и Google Maps API. В этом уроке мы рассмотрим, каким образом можно добавлять маркеры на карту и сохранять информацию о них в БД при помощи AJAX и PHP/MySQL.

Этот урок можно разбить на две части. В первой мы будем делать все для того, чтобы посредством AJAX сохранить информацию о добавленном маркере. Во второй части мы будем делать все для того, чтобы вытащить информацию о местоположении маркера из БД (посредством все того AJAX). За основу возьмем код из предыдущего урока. Что ж, приступим…

Шаг #1: Создаем форму для добавления местоположения

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

<form id="add-point" action="map-service.php" method="post">
<input type="hidden" name="action" value="savepoint" id="action">
<fieldset>
<legend>Добавить точку на карту</legend>
<div class="error" style="display:none;"></div>
<div class="input">
<label for="name">Название</label>
<input type="text" name="name" id="name" value="">
</div>
<div class="input">
<label for="address">Адрес</label>
<input type="text" name="address" id="address" value="">
</div>
<button type="submit">Добавить точку</button>
</fieldset>
</form>

Немного о форме:

  • Форма будет обрабатываться на сервере скриптом map-service.php;
  • Скрытое поле <input type="hidden" name="action" value="savepoint" id="action"> будет выступать в роли флага, который будет указывать скрипту на наше желание сохранить информацию в БД;
  • Пустой блок <div class="error" style="display:none;"></div> будет использоваться для вывода ошибок.

Шаг #2: Стилизуем форму

Добавим несколько строк CSS-кода:

#add-point { float:left; }
div.input { padding:3px 0; }
label { display:block; font-size:80%; }
input, select { width:150px; }
button { float:right; }
div.error { color:red; font-weight:bold; }

Шаг #3: Геокодируем введенный адрес

3a) Отключаем стандартную отправку формы

На этом шаге мы отключим стандартную отправку формы. Для этого будем использовать метод submit() jQuery с произвольной функцией внутри.

$("#add-point").submit(function(){
geoEncode();
return false;
});

3b) Добавляем геокодирование

Определим статусные сообщения геокодера:

var geo = new GClientGeocoder();

var reasons=[];
reasons[G_GEO_SUCCESS] = "Информация успешно добавлена";
reasons[G_GEO_MISSING_ADDRESS] = "Неверный адрес";
reasons[G_GEO_UNKNOWN_ADDRESS] = "Неизвестный адрес";
reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Недоступный адрес";
reasons[G_GEO_BAD_KEY] = "Неверный API-ключ";
reasons[G_GEO_TOO_MANY_QUERIES] = "Слишком много запросов";
reasons[G_GEO_SERVER_ERROR] = "Ошибка на сервере";

3с) Получаем координаты из адреса

function geoEncode() {
var address = $("#add-point input[name=address]").val();
geo.getLocations(address, function (result){
if (result.Status.code == G_GEO_SUCCESS) {
geocode = result.Placemark[0].Point.coordinates;
savePoint(geocode);
} else {
var reason="Код "+result.Status.code;
if (reasons[result.Status.code]) {
reason = reasons[result.Status.code]
}
$("#add-point .error").html(reason).fadeIn();
geocode = false;
}
});
}

Шаг #4: Отправляем информацию на сервер

function savePoint(geocode) {
var data = $("#add-point :input").serializeArray();
data[data.length] = { name: "lng", value: geocode[0] };
data[data.length] = { name: "lat", value: geocode[1] };
$.post($("#add-point").attr('action'), data, function(json){
$("#add-point .error").fadeOut();
if (json.status == "fail") {
$("#add-point .error").html(json.message).fadeIn();
}
if (json.status == "success") {
$("#add-point :input[name!=action]").val("");
var location = json.data;
addLocation(location);
zoomToBounds();
}
}, "json");
}

jQuery-метод $.post принимает следующие параметры:

  • URL для отправки информации: $(this).attr('action') принимает значение атрибута action формы;
  • Data – информация для отправки на сервер. Она представляет собой пары вида { name: "inputname", value: "inputvalue" }, которые создаются методом serializeArray() из элементов :input нашей формы;
  • Function – функция, которая сработает после получения ответа сервера. Она принимает один параметр, в котором, собственно, и содержится ответ от сервера;
  • Type of data – формат данных. Мы будем использовать JSON.

Шаг #5: Используем PHP для обработки формы

На этом шаге мы будем обрабатывать информацию, переданную на сервер при помощи jQuery.

5a) Проверяем переданные данные

Тут мы проверяем, действительно ли значением скрытого поля action является "savepoint". Затем, проверяем на корректность название места. Если что-то не так, то возвращаем сообщение об ошибке, которое будет показано в следующем подшаге.

<?php
if ($_POST['action'] == 'savepoint') {
$name = $_POST['name'];
if(preg_match('/[^\w\s]/i', $name)) {
fail('Неверное название.');
}
if(empty($name)) {
fail('Введите название.');
}
}
?>

Все это мы пишем в файл map-service.php.

5b) Возвращаем сообщение об ошибке как JSON-объект

function fail($message) {
die(json_encode(array('status' => 'fail', 'message' => $message)));
}

Для того, чтобы остановить выполнение скрипта при появлении ошибки, используем функцию die(). В качестве аргумента передаем ей результат выполнения функции json_encode() (которая, кстати, есть только в PHP версии 5.2+).

Шаг #6: Отображаем сообщение об ошибки при помощи jQuery

Пришло время написать обработчик ошибок на стороне клиента. Для начала скроем блок с ошибкой, если он уже был показан: для этого используем метод hide() jQuery. Далее, проверяем статус ответа от сервера (json.status) и показываем блок с ошибкой, если json.status имеет значение "fail". Для отображения блока с ошибкой испльзуем методы html() (который помещает текст ошибки в контейнер div с классом "error") и fadeIn() (который, собственно, этот контейнер потом отображает).

$("#add-point .error").hide();
if (json.status == "fail") {
$("#add-point .error").html(json.message).fadeIn();
}

Шаг #7: Создаем БД и сохраняем введенную информацию

Используя SQL, создадим таблицу со следующими полями: "name" (название места), "latitude" (широта), "longitude" (долгота) и "id" (идентификатор).

7a) Создаем таблицу

CREATE TABLE `locations` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) DEFAULT NULL,
`lat` FLOAT(15,11) DEFAULT NULL,
`lng` FLOAT(15,11) DEFAULT NULL,
PRIMARY KEY (`id`)
)

7b) Добавляем информацию в созданную таблицу

$query = "INSERT INTO locations SET name='$_POST[name]', lat='$lat', lng='$lng'";
$result = map_query($query);

if ($result) {
success(array('lat' => $_POST['lat'], 'lng' => $_POST['lng'], 'name' => $name));
} else {
fail('Невозможно добавить точку.');
}

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

Функция map_query():

function map_query($query) {
mysql_connect('MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD')
OR die(fail('Невозможно подключиться к БД.'));
mysql_select_db ('MYSQL_DATABASE');
return mysql_query($query);
}

Теперь – функция, которая срабатывает при успешном выполнении запроса:

function success($data) {
die(json_encode(array('status' => 'success', 'data' => $data)));
}

Шаг #8: Добавляем маркер на карту

Пришло время написать обработчик положительного ответа от сервера:

if (json.status == "success") {
$("#add-point :input[name!=action]").val("");
var location = json.data;
addLocation(location);
zoomToBounds();
}

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

function addLocation(location) {
var point = new GLatLng(location.lat, location.lng);
var marker = new GMarker(point);
map.addOverlay(marker);
bounds.extend(marker.getPoint());

$("<li />")
.html(location.name)
.click(function(){
showMessage(marker, location.name);
})
.appendTo("#list");

GEvent.addListener(marker, "click", function(){
showMessage(this);
});
}

Шаг #9: Загружаем информацию из БД и отображаем ее

Как только страница будет загружена, нам необходимо отобразить на карте все сохраненные нами точки. Самый простой способ это сделать – передать серверу GET-параметр, чтобы тот, в свою очередь, вернул соответствующий JSON-объект. Для этого используем метод $.getJSON:

$.getJSON("php/map-service.php?action=listpoints", function(json) {
// Тут будет функция из шага #11
});

Шаг #10: Получаем информацию из БД

if ($_GET['action'] == 'listpoints') {
$query = "SELECT * FROM locations";
$result = map_query($query);
$points = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
array_push($points, array('name' => $row['name'], 'lat' => $row['lat'], 'lng'=> $row['lng']));
}
echo json_encode(array("Locations" => $points));
exit;
}

Тут тоже все очень и очень просто: проверяем правильность GET-параметра и, если все нормально, то отдаем в качестве ответа JSON-объект, в котором содержится список всех точек, сохраненных в БД.

Шаг #11: Отображаем маркеры, соответствующие точкам

Обходим циклом по JSON-списку, который вернул сервер в качестве своего ответа:

if (json.Locations.length > 0) {
for (i=0; i<json.Locations.length; i++) {
var location = json.Locations[i];
addLocation(location);
}
zoomToBounds();
}

Шаг #12: Устанавливаем такой уровень зума, чтобы были видны все объекты

Определяем координаты границ, в которых находятся маркеры, отображаемые на карте:

var bounds = new GLatLngBounds();

Теперь, определяем метод zoomToBounds(), который будет устанавливать такой уровень зума, чтобы все маркеры отображались в видимой области карты:

function zoomToBounds() {
map.setCenter(bounds.getCenter());
map.setZoom(map.getBoundsZoomLevel(bounds)-1);
}

Ну вот и все. Ох уж мне эта динамика… А вот и пример. :)

понедельник, 18 января 2010 г.

Про кино №35 - "Театр абсурда какой-то"

Я никогда не любил (даже больше - терпеть не мог) фильмы Тарантино, кроме "От заката до рассвета" - так то про вампиров. А вот "Бесславные ублюдки" мне понравились примерно тем же, чем и "От заката...": полной бессмысленностью, абсурдностью и нереальностью происходящего не экране - такими, что ты погружаешься в них с головой и выныривать оттуда ну никак не хочется. В процессе просмотра складывается впечатление того, что именно так все и обстояло с исторической точки зрения, хотя, конечно, весь фильм - ни что иное, как стеб над всеми остальными фильмами о войне. Актеры подобраны идеально: особенно порадовали Питт (эдакий сумасшедший рубака, который свято верит в свою миссию) и Вальц (сыщик, ищейка, напомнивший мне, кстати, своего коллегу из отечественного мультфильма "Бременские музыканты").
Вдогонку немного напишу про фильм Гранта Хеслова "Безумный спецназ" (который в оригинале есть ни что иное, как "Мужики, пырящиеся на коз"). А это кино по абсурдности творящегося на экране уже приближается к творению братьев Коэнов "После прочтения сжечь" (благо, Клуни этому способствует). Но, в отличии от "После...", "Спецназ" гораздо более комедия - сквозь фарс и абсурд зритель должен рассмотреть призыв к человеколюбию и добру. Да к черту, собственно, поиски глубокого смысла - просто посмотрите и вдоволь посмейтесь.

jQuery и Google Maps API №1: Основы

jQuery и Google Maps API №1: Основы

А вот здесь-то мы и начнем использовать jQuery и Google Maps вместе. Очень сильно извращаться не станем, но будем использовать jQuery там, где это даст максимальную выгоду.

Вот, например, при помощи jQuery очень удобно создавать маркеры и обходить их массив, используя метод each(). Для начала расставим маркеры на карте:

// Устанавливаем 10 произвольных маркеров
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
var markers = [];
for (var i = 0; i < 10; i++) {
var point = new GLatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random());
marker = new GMarker(point);
map.addOverlay(marker);
markers[i] = marker;
}

А теперь – обойдем их и добавим к каждому обработчик события click: при щелчке левой кнопкой мыши по маркеру карта будет отцентрирована на этот маркер. Сначала мы получаем координаты маркера при помощи метода getLatLng(), а затем – центрируем карту по этим координатам при помощи метода panTo().

$(markers).each(function(i,marker){
GEvent.addListener(marker, "click", function(){
map.panTo(marker.getLatLng());
});
});

Далее, сделаем список, связанный с расставленными по карте маркерами. Добавляем список:

<ul id="list"></ul>

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

<style type="text/css" media="screen">
#map { float:left; width:500px; height:500px; }
#list { float:left; width:200px; background:#eee; list-style:none; padding:0; }
#list li { padding:10px; }
#list li:hover { background:#555; color:#fff; cursor:pointer; cursor:hand; }
</style>

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

$("<li />")
.html("Маркер №"+i)
.click(function(){
map.panTo(marker.getLatLng());
})
.appendTo("#list");

Код этот отвечает вот за что: делает элемент списка кликабельным и при клике центрирует карту по соответствующему элементу списка маркеру.

Теперь – выводим симпатичное сообщение вместо стандартного инфо-окна. Для начала создадим блок с текстом сообщения:

<div id="message" style="display:none;">
Какое-то сообщение тут.
</div>

Далее, слегка его стилизуем:

#message { position:absolute; padding:10px; background:#555; color:#fff; width:75px; }

Теперь бы нужно как-то поместить этот div с сообщением на карту. Вообще, карта представляет собой кучу слоев, которые также являются div’ами. Для того, чтобы узнать, в каком div’е на карте содержится маркер, мы будем использовать метод getPane() с параметром G_MAP_FLOAT_SHADOW_PANE, который лучше всего подходит для наших целей.

$("#message").appendTo(map.getPane(G_MAP_FLOAT_SHADOW_PANE));

Далее, для того, чтобы корректно отображалось наше самопальное информационное окно, нам необходимо заменить строчку map.panTo(marker.getLatLng(); на displayPoint(marker, i);, вызывающую функцию displayPoint(), код которой показан ниже.

function displayPoint(marker, i){
map.panTo(marker.getPoint());

var markerOffset = map.fromLatLngToDivPixel(marker.getPoint());
$("#message").show().css({ top:markerOffset.y, left:markerOffset.x });
}

Мы переложили функционал метода panTo() на плечи новой, самописной функции, главной изюминкой которой является метод fromLatLngToDivPixel(), который конвертирует значение координат маркера в его положение в пикселях относительно слоя с картой.

Нужно же как-то закончить нашу свистопляску? Закончим мы ее путем добавления обработчика события "moveend" для карты: после того, как карта закончит свое движение в направлении маркера, по которому был совершен клик, сработает jQuery-метод fadeIn() для блока с сообщением.

function displayPoint(marker, index){
$("#message").hide();

var moveEnd = GEvent.addListener(map, "moveend", function(){
var markerOffset = map.fromLatLngToDivPixel(marker.getLatLng());
$("#message")
.fadeIn()
.css({ top:markerOffset.y, left:markerOffset.x });

GEvent.removeListener(moveEnd);
});
map.panTo(marker.getLatLng());
}

Ну вот: что хотели, то и получили. :) Тут - работающий пример.

воскресенье, 17 января 2010 г.

Музыкальное...

Оказывается, и на постсоветских просторах существует нечто, похожее на modern romance (Norah Jones, Sasha Dobson), но еще не до конца определившееся. Называется это нечто Put:Pur и вот один из их клипов: очень солнечный, яркий, хорошо (удивительно!) снятый и очень позитивный.

суббота, 16 января 2010 г.

Убей себя в сети!

Не так давно на Хабре проскочил вот этот замечательный топик, рассказывающий про сервис Web 2.0 Suicide Machine - эдакий анти-интернет-социальный проект, который убивает пользовательские аккаунты в буржуйских Facebook, Twitter, Linkedin и Myspace. У меня сразу же проскочила мысля: "Вот бы заиметь русский аналог этого сервиса, который бы зачищал профиль вКонтакте!" Видимо, такая мысль посетила не меня одного. :)
Встречайте - unVKontakte. Так что, если кто-то вдруг обнаружит, что я пропал из его списка друзей - не серчайте...

вторник, 12 января 2010 г.

Тост!

Сегодня утром родилось у меня замечательное четверостишие-тост:



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

Вот так вот. :)

Про Parental Control в последней прошивке для D-Link 2640U...

Как бы сказал мой друг Виктор: "Олег, по-моему, ты въебался в раму!" И это, наверное, так и есть. Это ж каким долбоебом нужно быть, чтобы в разделе Parental Control админки роутера взять и добавить в список запрещенных URL'ов адреса vk.com и vkontakte.ru?! Нет придела совершенству! Это я себя так ограничиваю: крышу рвет просто нереально. Остается сказать спасибо ребятам из D-Link. :)