misc/class
lib/jquery_pnotify, lib/moment, lib/lodash, misc/notification, site/engine, misc/social
if( $.browser.msie && $.browser.version <= 8 ) include('lib/respond'); $._social.__cfg = {"init":[{"service":"basic"},{"fb_app_id":"1997094873850041","service":"fb"},{"vk_app_id":"2978320","service":"vk"},{"service":"twi"}],"like":[{"service":"fb"},{"service":"vk"},{"via":"","channel":"","hash_tag":"","service":"twi"}]}; window._SiteEngine = new classes.SiteEngine( { user_id: 0, controller: 'content_tape', action: 'view', content_css_version: '1459538664', social_enabled: 0} );

Faiwer

Блог web-программиста

node-forever

1 сентября 2015

Внезапно оказался перед фактом ― закончилось место на VPS. Оказалось, что node-forever съел своими логами 21 GiB места на винте. Приложение упрямо не хотело подниматься, падало, forever это писал в логи и снова пытался его поднять. Забавно…

Заметка о восстановлении данных

5 июля 2015

Как уже и писал ранее, случилась у меня проблема с удалением файлов. GoPro подключается к ПК не как USB-flash, а как MTP (Media Transfer Protocol). Это выражется в том, что не все файлы, размещённые на носителе видны, тем что не удаётся посмотреть начало какого-нибудь ролика не скачав его целиком, а также в том, что мой LinuxMint отказывается скачивать с такого вот MTP-носителя файлы, ибо соединение попросту зависает при любой операции.

Ну да ладно. Есть ультрабук с Win8 на борту. Можно качать через него, ведь он файлы видит. И дёрнул меня чёрт сократить время, и скопировать сразу на флешку. Да и не скопировать а "вырезать" и "вставить". Получив несколько невнятных ошибок я столкнулся с ситуацией, когда на SD-карте файлов уже нет, а на флешке их и не появлялось вовсе. Т.е. они утеряны.

В очередной раз высказав всё, что я думаю об MTP и GoPro я подумал, что файлы ведь можно восстановить. Ибо они не должны быть ничем перезаписаны. Должны лежать как на ладони, быстро находиться и идеально восстанавливаться. Картридера у меня увы нет, мой One PlusOne не умеет внешние SD-карты. Но старый SGS II умеет. И посему я решил воспользоваться android-восстанавливалками.

  • Первым в ход пошёл DiskDigger undelete. Не сказать, чтобы софтина понравилась, но она смогла найти 1 старый 3 MiB файл, совершенно бесполезный, но это уже хотя бы отличный от 0 результат. Ушло у неё на это около часа.
  • Вторым был Hexamob Recovery Lite. Первое, что он сделал ― бросил меня в Google Play покупать платную версию. Логика железная, я скачал бесплатную версию, чтобы убедиться что она хотя бы найти что-то сможет, а меня уже швыряют покупать платную. Вы за кого держите пользователя? Следующим этапом было то, что нет никаких по сути опций и настроек, он просто спрашивает где сканировать и начинает сканировать. Никакой индикации прогресса нет, просто отображении анимации, мол "я ещё не завис". Ну и всякая реклама. Потерпев минуты 3 этот идаотизм, софтина ушла в утиль. Хороший пример того, как нельзя писать подобный софт.
  • Третьим был Undelete for Root Users. Порадовал вменяемый и приятный на вид интерфейс, удобное управление. Не порадовало то, что он не нашёл ничего, совсем. На 32GiB ушло 1ч 11м.

Я упустил 1 момент. Дело в том, что 1 файл из 3 мне всё таки удалось с самого начала вырезать-вставить. Его я обкромсал, как обычно ffmpeg-ом, срезав по краям лишнее и снёс оригинал через shift+delete из caja. Затем, потратив часа 3 на восстановление файлов с SD-карты,  я вернулся к обрезанному видео. И понял, что, по запарке, срезал на несколько секунд больше, очень зря… А оригинал уже удалил. Решил восстановить уже этот файл. Проблема усугублялась тем, что файл лежал не на ext3 разделе, а на ntfs

  • Вначале я наткнулся на ntfsundelete. Это консольная утилита, которой нужно указать раздел и она найдёт все легко-восстанавливаемые файлы, указав их размер, имя по возможности, inode и пр. Мой файл там нашёлся. Восстановив его (4 GiB) я получил 4 GiB кирпич, который ничем не открывается. Я подумал, что сие же mp4, а значит его можно как-нибудь починить. Полез рыскать по сети:
    • mplayer его показывает как какую то разноцветную жуть, мечту эпилептиков.
    • ffmpeg -i грязно ругался.
    • попробовал Video Repair. С ней возникли некоторые сложности, но в конце концов она просто помирала на файле с какими-то невнятными ошибками.
    • попробовал mp4repair.org. На сайте указано, что смело указывайте ему даже huge mp4 файлы, чем я и воспользовался. На ~30% всё повисает…
  • Затем, я вспомнил, что файл был удалён ещё и в USB 3.0 Flash-ки. Попробовал Recuva. Нужный мне файл она нашла дважды. 1 пометила как испорченный и переписанный (причём файлом, который был на флешке уже месяц), второй как идеальный, без повреждений. Интересная форма шизофрении. Восстановив "идеальный", я столкнулся с тем, что получил такой же кирпич, как и в случае, ntfsundelete.

Учитывая, что эти 3 видео не являются для меня чем-то жизненно важным, я, убив себе настроение, закончил истязания и забил. Разве что, вот ещё на эту заметку хватило. Пожалуй, стоит купить внешний USB кардридер.

UPD1: Купил картридер. Картридер работает без каких-либо проблем. Попробовал что-нибудь найти через testdist. Тщетно. Из Win8.1 попробовал через Recuva, она в отличии от android приложений, нашла множество файлов. Восстановил те из них, которые могут быть искомыми. Все файлы ― кирпичи. Для "откирпичивания" использовал Video Repair. Получается чёрт знает что. 30% видео (отрывками по несколько секунд) идут без помех, оставшееся ― помесь с жуткими артефактами, всякими сдвигами во времени и прочим цирком.

Как найти ближайший видимый domElement в скролируемом viewPort-е

26 июня 2015

Возникла задача ― в скролируемом контейнере найти первый видимый domElement. Я подумал, что, наверняка, это довольно частая задача, и должно быть множество разных готовых решений. Порыскав по сети я нашёл лишь множество вариаций одного и того же: рекурсивный обход всего древа domElement-ов, с рассчётом их границ. В голову полезли варианты с бинарным поиском по тому же принципу, но уж больно не хотелось с этим всем связываться. Как то уж слишком сурово, для такой мелочной задачи. Должен быть "нативный" инструмент.

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

  • У контейнера, который содержит искомые domElement-ы вызываем getBoundingClientRect. Получаем его расположение на экране
  • Вычисляем координаты какого-либо участка из viewPort-а, где должен находится искомый domElement
  • Вызываем document.elementFromPoint, указав нужные координаты экрана
  • profit…

Решение сгодится не для любого случая. Но мне вполне подошло.

Кирилица и SmartGit

11 апреля 2015

Извечная беда с горячими клавишами в нестандартной (т.е. английской) раскладке. Наиболее часто попадается в Java и QT приложениях. Наиболее остро я на это натыкаюсь при использовании Mate окружения в свежем LinuxMint-е. Обе баги (что QT, что Java) уже исправлены, что, почему то не сказывается даже на свежих билдах софта, к примеру SmartGit-а. В очередной раз вооружившись поисковиком я стал искать решения в обход. И нашёл! Хороший человек написал небольшую java-утилиту для решения проблем с горячими клавишами. Вся соль в том, что необходимо запустить jar-ки с флагом -javaagent к java. В описании к репозиторию указано, как правильно это сделать для Intelli Idea и ещё ряда приложений. А для SmartGit-а вот правильное решение:

  • Создать файл ~/.smartgit/smartgit.vmoptions
  • Вписать туда -javaagent:%jarpath%/LinuxJavaFixes-%version%.jar=swt. Вместо %jarpath% указать путь к скачанным с github-а файлам, а вместо %version% текущую версию jar-ки. Обратите внимание на =swt, без этого в SmartGit ничего не заработало. SWT это фреймворк для Java, который использует SmartGit
  • Готово!

Осталось найти рецепт для QT-приложений :( Похоже, что там надо насильно ставить себе QT5.5+ и собирать из исходников каждое проблемное приложение :(

Простой proxy-сервер на iojs

9 апреля 2015

Для нужд разработки возникла необходимость в proxy-овании некоторых запросов, в обход CORS-а. Погуглив и слегка причесав код, получилось следующее:

"use strict";

/**
 * run: iojs --harmony_arrow_functions proxy.js
 *
 * nginx:
 * location ~ ^/api.*$ {
 * 	proxy_pass http://127.0.0.1:3001;
 * 	proxy_set_header X-Real-IP $remote_addr;
 * 	proxy_set_header Host $host;
 * 	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 * }
 */

let hostname = '%hostname%';
let port = 3001;
let auth = '%user%:%pass%';
let http = require('http');

http.createServer((clientReq, clientRes) =>
{
	let opts =
	{
		hostname: hostname,
		port: 80,
		path: clientReq.url,
		auth: auth,
		headers: clientReq.headers,
		method: clientReq.method
	};
	opts.headers.host = hostname;

	console.info('serve: %s %s', clientReq.method, clientReq.url);

	let proxy = http.request(opts, (proxyRes) =>
	{
		proxyRes.addListener('data', (chunk) => clientRes.write(chunk, 'binary'));
		proxyRes.addListener('end', () => clientRes.end());
		clientRes.writeHead(proxyRes.statusCode, proxyRes.headers);
	});

	clientReq.addListener('data', (chunk) => proxy.write(chunk, 'binary'));
	clientReq.addListener('end', () => proxy.end());
}).listen(port);

Запускается путём выполнения iojs --harmony_arrow_functions proxy.js, логирует все запросы в консоль. Точно умеет POST, GET, отдавать статику… Для простых нужд вполне сгодится. Жаль браузеры пока толком не умеют arrow functions :(