Мы хотим запустить trac. обычно его запускают из-под Apache, но мы не будем этого делать. Вместо этого мы запустим Trac Standalone - самостоятельный веб-сервер, который и будет хостить trac. На странице проекта Trac Standalone можно подробнее прочитать об этом способе запуска.
Считаем, что trac у нас уже установлен.
Запустим trac на 9990 порту на проекте prj1:
$ tracd --port 9990 /home/trac/prj1
Отлично, tracd стартовал.
Теперь подумаем про аутентификацию пользователей.
Вначале создаем даем двум пользователям, vasya и petya, привилегии админов trac:
$ trac-admin /home/trac/prj1 permission add vasya TRAC_ADMIN
$ trac-admin /home/trac/prj1 permission add petya TRAC_ADMIN
Теперь создаем файлик, который будет содержать имена пользователей и хеш-суммы их паролей. Каждая строка в файле формируется следующим образом:
username:realm:md5sum(username:realm:password)
Например, если пользователь petya имеет пароль password1, а realm мы задали как 'trac', то строка для petya в файле будет такой:
petya:trac:7f9c7f2ecd9894a028ce8c10ede46719
где 7f9c7f2ecd9894a028ce8c10ede46719 - md5-хешсумма от строки 'petya:trac:password1'.
Пусть мы создали этот файл для двух пользователей (пароль для vasya: 'password2'):
petya:trac:7f9c7f2ecd9894a028ce8c10ede46719
vasya:trac:1bacebce4824deae3bb3c9851c22fbbc
Теперь этот файл (trac_users.txt) можно указать в настройках tracd:
$ tracd --port 9990 --auth=prj1,trac_users.txt,trac /home/trac/prj1
На этом все.
Общее·количество·просмотров·страницы
Java Dev Notes - разработка на Java (а также на JavaScript/Python/Flex и др), факты, события из АйТи
среда, 23 июня 2010 г.
воскресенье, 20 июня 2010 г.
Назначение и изменение прав на каталоги и файлы в unix
Назначение и изменение прав на каталоги и файлы в unix:
Стандартные права Unix, SUID, SGID, Sticky биты
Хорошее, годное и подробное руководство.
Стандартные права Unix, SUID, SGID, Sticky биты
Хорошее, годное и подробное руководство.
вторник, 15 июня 2010 г.
Связка nginx - Tomcat: прокидывание реального IP пользователя до Томката
При разработке Evaphone мы решили все томкаты проксировать с помощью nginx. Это хорошо известная схема - frontend server - backend server. Frontend сервер (в нашем случае - nginx) занимается отдачей статики, а на backend он проксирует запросы на динамику. Такая схема работы позволяет снизить нагрузку на "тяжелый" бэкенд и увеличить производительность приложения.
Внутри нашего приложения используется информация о пользователи, а именно, IP-адрес. Когда запрос проксируется nginx'ом, то, естественно, реальный IP-адрес пользователя подменяется адресом машины, на которой работает nginx. Однако, nginx не "теряет" реальный IP-адрес. Вместо этого он передает его в HTTP-заголовке "x-real-ip". Это настраивается следующим конфигом nginx:
В этот конфиг вместо ___tomcat_app_url___ нужно подставить URL приложения на томкате, куда будет передаваться запрос. Например, может быть следующий URL: http://127.0.0.1:8080/myapp (это если tomcat и nginx работают на одной машине). Этот конфиг говорит томкату, что все запросы по адресу <ваш_ip>/tomcat нужно проксировать на ___tomcat_app_url___.
Теперь рассмотрим настройку Tomcat. Мы знаем, что реальный айпишник приходит к нам в заголовке запроса "x-real-ip". Подмену адреса (вернее, вытягивание реального айпишника) мы делаем с помощью сервлетного фильтра:
Код достаточно понятный. Что мы делаем:
Осталось только замэппить наш фильтр на все приложение. В файле web.xml добавляем следующие строки:
На этом все!
Пара ссылок:
Настройка nginx для работы с apache и tomcat серверами на примере Ubuntu 10.04 Server
Nginx + Tomcat - тред на форуме nginx
JSP+Tomcat+nginx - тред на форуме RSDN
UPD 11 Июля 2010: Улучшенный код:
Внутри нашего приложения используется информация о пользователи, а именно, IP-адрес. Когда запрос проксируется nginx'ом, то, естественно, реальный IP-адрес пользователя подменяется адресом машины, на которой работает nginx. Однако, nginx не "теряет" реальный IP-адрес. Вместо этого он передает его в HTTP-заголовке "x-real-ip". Это настраивается следующим конфигом nginx:
location = /tomcat {
proxy_pass ___tomcat_app_url___;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
В этот конфиг вместо ___tomcat_app_url___ нужно подставить URL приложения на томкате, куда будет передаваться запрос. Например, может быть следующий URL: http://127.0.0.1:8080/myapp (это если tomcat и nginx работают на одной машине). Этот конфиг говорит томкату, что все запросы по адресу <ваш_ip>/tomcat нужно проксировать на ___tomcat_app_url___.
Теперь рассмотрим настройку Tomcat. Мы знаем, что реальный айпишник приходит к нам в заголовке запроса "x-real-ip". Подмену адреса (вернее, вытягивание реального айпишника) мы делаем с помощью сервлетного фильтра:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.FilterConfig;
import javax.servlet.FilterChain;
import javax.servlet.ServletResponse;
import javax.servlet.ServletRequest;
import javax.servlet.Filter;
public class GetRealIPFilter implements Filter {
public static final String X_FORWARDED_FOR = "x-forwarded-for";
public static final String X_REAL_IP = "x-real-ip";
public GetRealIPFilter() {
//System.out.println("[GetRealIPFilter.GetRealIPFilter]");
}
public void destroy() {
//System.out.println("[GetRealIPFilter.destroy]");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
//System.out.println("[GetRealIPFilter.doFilter]");
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest)request;
final String realIp = httpRequest.getHeader(X_REAL_IP);
final String realHost = httpRequest.getHeader(X_FORWARDED_FOR);
//System.out.println("[GetRealIPFilter.doFilter], realIp='"+realIp+"'");
//System.out.println("[GetRealIPFilter.doFilter], realHost='"+realHost+"'");
if (realIp != null) {
//System.out.println("[GetRealIPFilter.doFilter], realIp != null, wrap request");
filterChain.doFilter(
new HttpServletRequestWrapper(httpRequest) {
public String getRemoteAddr() {
return realIp;
}
public String getRemoteHost() {
return realHost;
}
},
response
);
return;
}
}
filterChain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
//System.out.println("[GetRealIPFilter.init]");
}
}
Код достаточно понятный. Что мы делаем:
- Проверяем, есть ли заголовок "x-real-ip". Если его нет, то ничего не делаем, т.е. все остается по-старому. Tomcat продолжит принимать запросы напрямую
- Если заголовок "x-real-ip" присутствует, то в цепочку фильтров мы передаем не пришедший к нам от nginx request, а его обертку HttpServletRequestWrapper, в которой мы подменили методы getRemoteAddr и getRemoteHost так, чтобы они выдавали данные, пришедшие в заголовках "x-real-ip", "x-forwarded-for" соответственно.
Осталось только замэппить наш фильтр на все приложение. В файле web.xml добавляем следующие строки:
<filter>
<filter-name>get_real_ip_filter</filter-name>
<filter-class>GetRealIPFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>get_real_ip_filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
На этом все!
Пара ссылок:
Настройка nginx для работы с apache и tomcat серверами на примере Ubuntu 10.04 Server
Nginx + Tomcat - тред на форуме nginx
JSP+Tomcat+nginx - тред на форуме RSDN
UPD 11 Июля 2010: Улучшенный код:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
//System.out.println("[GetRealIPFilter.doFilter]");
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest)request;
final String realIp = httpRequest.getHeader(X_REAL_IP);
final String realHost = httpRequest.getHeader(X_FORWARDED_FOR);
//System.out.println("[GetRealIPFilter.doFilter], realIp='"+realIp+"'");
//System.out.println("[GetRealIPFilter.doFilter], realHost='"+realHost+"'");
if (realIp != null) {
if (realHost != null) {
filterChain.doFilter(new HttpServletRequestWrapper(httpRequest) {
public String getRemoteAddr() {return realIp;}
public String getRemoteHost() {return realHost;}
},response);
return;
} else {
filterChain.doFilter(new HttpServletRequestWrapper(httpRequest) {
public String getRemoteAddr() {return realIp;}
},response);
return;
}
} else if (realHost != null) {
filterChain.doFilter(new HttpServletRequestWrapper(httpRequest) {
public String getRemoteHost() {return realHost;}
},response);
return;
}
}
filterChain.doFilter(request, response);
}
суббота, 12 июня 2010 г.
Установка yum на CentOS 5.4 (Final):
Ставим yum на CentOS 5.4 (Final):
cd ~/
mkdir temp
cd temp
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-3.2.22-26.el5.centos.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/python-iniparse-0.2.3-4.el5.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/rpm-python-4.4.2.3-18.el5.i386.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/python-urlgrabber-3.1.0-5.el5.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-fastestmirror-1.1.16-14.el5.centos.1.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-metadata-parser-1.1.2-3.el5.centos.i386.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/m2crypto-0.16-6.el5.6.i386.rpm
rpm -ivh *rpm
список RPM-пакетов для CentOS можно посмотреть по ссылке http://mirror.centos.org/centos/5/os/i386/CentOS
Здесь http://www.electrictoolbox.com/install-yum-with-rpm-on-centos/ раскрывается похожая тема
cd ~/
mkdir temp
cd temp
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-3.2.22-26.el5.centos.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/python-iniparse-0.2.3-4.el5.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/rpm-python-4.4.2.3-18.el5.i386.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/python-urlgrabber-3.1.0-5.el5.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-fastestmirror-1.1.16-14.el5.centos.1.noarch.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/yum-metadata-parser-1.1.2-3.el5.centos.i386.rpm
wget http://mirror.centos.org/centos/5/os/i386/CentOS/m2crypto-0.16-6.el5.6.i386.rpm
rpm -ivh *rpm
список RPM-пакетов для CentOS можно посмотреть по ссылке http://mirror.centos.org/centos/5/os/i386/CentOS
Здесь http://www.electrictoolbox.com/install-yum-with-rpm-on-centos/ раскрывается похожая тема
вторник, 8 июня 2010 г.
Установка переменных среды для Java, Apache Tomcat
Устанавливаем переменные среды JAVA_HOME, CATALINA_HOME. Только что столкнулся с тем, что если устанавливать переменные среды через export из SSH, то они не сохраняются между SSH-сессиями. В этом случае их надо прописать в файле ~/bashrc или ~/bash_profile.
Прописал следующее, теперь все работает:
Добавил следующие строки в файл ~/bashrc
JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_HOME
CATALINA_HOME=/usr/java/apache-tomcat-6.0.26
export CATALINA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
Весь же файл ~/bashrc выглядит так
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_HOME
CATALINA_HOME=/usr/java/apache-tomcat-6.0.26
export CATALINA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
Прописал следующее, теперь все работает:
Добавил следующие строки в файл ~/bashrc
JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_HOME
CATALINA_HOME=/usr/java/apache-tomcat-6.0.26
export CATALINA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
Весь же файл ~/bashrc выглядит так
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
JAVA_HOME=/usr/java/jdk1.6.0_20
export JAVA_HOME
CATALINA_HOME=/usr/java/apache-tomcat-6.0.26
export CATALINA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
Установка и удаление java на CentOS
Устанавливаем JDK на CentOS:
UPDATE:
Как удалять JRE
Вот ссылка на java.com: How do I uninstall Java for Linux ?
Если JRE была поставлена из RPM:
1) проверяем, поставлена ли JRE из rpm:
rpm -qa | grep jre
2) удаляем
rpm -e jre-1.5.0_21-fcs
3) Профит! (иногда надо перезагрузить машину)
- Скачиваем jdk-6u20-linux-i586.bin с сайта http://java.sun.com
- Заливаем его на сервер в каталог /usr/java
- Меняем права $>chmod 755 jdk-6u20-linux-i586.bin
- Выполняем #./jdk-6u20-linux-i586.bin
- Набираем yes для согласия с лицензией, далее идет установка
- Устанавливаем переменную среды # export JAVA_HOME=/usr/java/jdk1.6.0_20
Затем кладем ее в PATH:
# export PATH=$PATH:$JAVA_HOME/bin - Проверочка #java -version
Получаем:
# java -version
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
UPDATE:
Как удалять JRE
Вот ссылка на java.com: How do I uninstall Java for Linux ?
Если JRE была поставлена из RPM:
1) проверяем, поставлена ли JRE из rpm:
rpm -qa | grep jre
2) удаляем
rpm -e jre-1.5.0_21-fcs
3) Профит! (иногда надо перезагрузить машину)
воскресенье, 30 мая 2010 г.
Google Maps V3 - метод Map.getBounds() возвращает undefined
Сегодня столкнулся с тем, что в Google Maps V3 getBounds() у объекта карты возвращает undefined. Пример кода:
Оказывается, дело в том, что сразу после создания карта еще не инициализировалась. Поэтому ее границы не определены, и поэтому метод getBounds() возвращает undefned
Поэтому границы карты следует получать, после того, как карта инициализировалась. Для этого нужно ставить обработчик события idle. Вот как это делается:
Также проблема обсуждается Stack Overflow: Google Maps Api v3 - getBounds is undefined, а также есть issue на Google Code: Issue 1692: Map bounds not available on first load of the map.
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(60, 60);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var bounds = map.getBounds();
console.debug(bounds);
if (!bounds) {
alert('Не могу определить границы карты сразу после ее создания!');
}
var loc= new google.maps.LatLng(60.0, 60.0);
var marker = new google.maps.Marker({
position: loc,
map: map
});
bounds = map.getBounds();
console.debug(bounds);
if (!bounds) {
alert('Не могу определить границы карты даже после добавления маркера!');
}
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>
Оказывается, дело в том, что сразу после создания карта еще не инициализировалась. Поэтому ее границы не определены, и поэтому метод getBounds() возвращает undefned
Поэтому границы карты следует получать, после того, как карта инициализировалась. Для этого нужно ставить обработчик события idle. Вот как это делается:
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(60, 60);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(60.0, 60.0);,
map: map
});
google.maps.event.addListenerOnce(map, 'idle', function(){
console.log('IDLE EVENT CallBack');
console.debug(map.getBounds());
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>
Также проблема обсуждается Stack Overflow: Google Maps Api v3 - getBounds is undefined, а также есть issue на Google Code: Issue 1692: Map bounds not available on first load of the map.
Ярлыки:
google maps
пятница, 14 мая 2010 г.
Итерация по словарю в шаблонах Google App Engine
Возникла задачка: как отрендерить в шаблон GAE данные, которые содержатся в словаре. В шаблон передается словарь, который содержит статистику по регионам. Ключами являются названия регионов, а значениями - количество неких объектов в этом регионе.
Нам нужно в шаблоне выводить список регионов + соответсвуюшую цифру. Делается это так:
Здесь areaStat - это имя словаря, i.0 - ключ, i.1 - значение.
Нам нужно в шаблоне выводить список регионов + соответсвуюшую цифру. Делается это так:
"area" : {
{% for i in areaStat.items %}
"{{ i.0 }}" : "{{ i.1 }}"{% if not forloop.last %},{% endif %}
{% endfor %}
}
Здесь areaStat - это имя словаря, i.0 - ключ, i.1 - значение.
Ярлыки:
google app engine,
python,
templates
Знакомство с Блогуном
Решил познакомиться с работой Блогуна. Посмотрим, что за сервис, как он устроен.
Ярлыки:
блогун
среда, 12 мая 2010 г.
Публикация ссылок ВКонтакте
Сайт/блог полезно снабдить конпкой, через которую пользователи могут запостить ссылку на сайт в социальные сети, системы закладок, твиттер и т.п. С недавних пор такую функциональность приобрел и vkontakte.ru.
Добавить кнопку для публикации ссылки ВКонтакте очень просто - для этого всего лишь надо добавить пару строк в код странички. Подробнее читай здесь: ВКонтакте - Публикация ссылок.
Добавить кнопку для публикации ссылки ВКонтакте очень просто - для этого всего лишь надо добавить пару строк в код странички. Подробнее читай здесь: ВКонтакте - Публикация ссылок.
среда, 28 апреля 2010 г.
Консоль Firebug не показывает свойство next у объектов
Обнаружил интересный косяк Firebug: почему-то в консоли Firebug не отображается свойство next у объекта.
Вводим следующий код:
Смотрим скриншот - не показывается свойство next:

Но в то же время, можно вывести в консоль значение этого свойства:
Скриншот:

Firefox:
Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
Firebug: 1.5.3.
Вот такие интересные дела творятся в датском королевстве...
Вводим следующий код:
var o = {};
o.next = 'suxxx';
o.next1 = '111';
console.debug(o);
Смотрим скриншот - не показывается свойство next:

Но в то же время, можно вывести в консоль значение этого свойства:
var o = {};
o.next = 'suxxx';
o.next1 = '111';
console.debug(o.next);
Скриншот:

Firefox:
Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
Firebug: 1.5.3.
Вот такие интересные дела творятся в датском королевстве...
Ярлыки:
firebug,
javascript
вторник, 20 апреля 2010 г.
Дистрибутивы ExtJS
Выкладываю дистрибутивы ExtJS, начиная с версии 3.0.0. На офсайте ExtJS нет ссылок на архивы (по крайней мере, для бесплатных юзеров). А иногда нужно обратиться к старой версии ExtJS. Сейчас выложено 4 версии: 3.0.0, 3.0.3, 3.1.0, 3.2.0.
ExtJS 3.0.0
ExtJS 3.0.3
ExtJS 3.1.0
ExtJS 3.2.0
UPDATE 10 Мая 2010 года: ExtJS 3.2.1
UPDATE 12 Октября 2010 года: ExtJS 3.3.0
ExtJS 3.0.0
ExtJS 3.0.3
ExtJS 3.1.0
ExtJS 3.2.0
UPDATE 10 Мая 2010 года: ExtJS 3.2.1
UPDATE 12 Октября 2010 года: ExtJS 3.3.0
Ярлыки:
ExtJS
Обрезание ExtJS
Рассмотрим, что можно выкинуть из библиотеки ExtJS, когда кладем ее в продакшн-версию приложения. Из-коробки ExtJS приходит со множеством файлов/папок, которые совсем не нужны для работы приложения. Сюда входят документация, примеры, тесты, темы и др. Вот мы и разберем, что можно выкинуть, а что можно оставить.
Вот структура каталогов ExtJS 3.2.0 (содержимое корневого каталога ExtJS):
+ файлы:
Сразу удаляем каталоги:
и все файлы в корневом каталоге, кроме ext-all.js. Так что из каталогов у нас остается только adapter, resources. Дальше правим их.
Заходим в adapter. Видим каталоги
Удаляем все, кроме ext. В ext есть два файла: ext-base.js, ext-base-debug.js. Файл ext-base-debug.js удаляем, он нам не нужен. На этом с каталогом adapter закончили.
Теперь переходим в resources. В нем есть каталоги css, images и несколько файлов: charts.swf, expressinstall.swf и resources.jsb. Файлы не трогаем. Переходим в css. В нем несколько каталогов, которые содержат различные темы оформления и прочее. Как правило, это все не нужно. В css удаляем все, оставляем только файл ext-all.css. Теперь идем в images. Там есть несколько каталогов с изображениями для разных тем оформления. Нам нужна только тема default. Поэтому удаляем все каталоги, кроме default.
На этом все. В результате этих действий ExtJS похудел с 44 472 007 байт (42 Мб) до 1 390 373 байт (1.32 Мб). Happy coding!
Вот структура каталогов ExtJS 3.2.0 (содержимое корневого каталога ExtJS):
adapter
docs
examples
pkgs
resources
src
test
welcome
+ файлы:
ext.jb2
ext-all.js
ext-all-debug.js
gpl-3.0.txt
INCLUDE_ORDER.txt
index.html
license.txt
Сразу удаляем каталоги:
docs
examples
pkgs
src
test
welcome
и все файлы в корневом каталоге, кроме ext-all.js. Так что из каталогов у нас остается только adapter, resources. Дальше правим их.
Заходим в adapter. Видим каталоги
ext
jquery
prototype
yui
Удаляем все, кроме ext. В ext есть два файла: ext-base.js, ext-base-debug.js. Файл ext-base-debug.js удаляем, он нам не нужен. На этом с каталогом adapter закончили.
Теперь переходим в resources. В нем есть каталоги css, images и несколько файлов: charts.swf, expressinstall.swf и resources.jsb. Файлы не трогаем. Переходим в css. В нем несколько каталогов, которые содержат различные темы оформления и прочее. Как правило, это все не нужно. В css удаляем все, оставляем только файл ext-all.css. Теперь идем в images. Там есть несколько каталогов с изображениями для разных тем оформления. Нам нужна только тема default. Поэтому удаляем все каталоги, кроме default.
На этом все. В результате этих действий ExtJS похудел с 44 472 007 байт (42 Мб) до 1 390 373 байт (1.32 Мб). Happy coding!
Ярлыки:
ExtJS
четверг, 15 апреля 2010 г.
Мартовская статистика CTR для рекламных показов на мобильных телефонах, версия от Smaato
Источник: ТехКранч, Symbian Still Leading In Mobile Ad Click-Through Rates, Android Dropping Fast.
Итак, рекламная сеть Smaato зарелизила мартовскую статистику (Март 2010 года) по CTR для показов рекламных объявлений на мобильных телефонах.

Самый высокий CTR на Symbian - 156, затем идут feature phones (телефоны с проприетарной ОС от производителя), затем WinMo, iPhone и Android. Ниже Андроида только RIM, Palm. Причем Андроид скатился со второго места в Январе-Феврале 2010 на пятое в марте.
Итак, рекламная сеть Smaato зарелизила мартовскую статистику (Март 2010 года) по CTR для показов рекламных объявлений на мобильных телефонах.
Самый высокий CTR на Symbian - 156, затем идут feature phones (телефоны с проприетарной ОС от производителя), затем WinMo, iPhone и Android. Ниже Андроида только RIM, Palm. Причем Андроид скатился со второго места в Январе-Феврале 2010 на пятое в марте.
Ярлыки:
android,
mobile,
mobile ads,
money
Финалисты The Next Web Paypal X Startup Rally 2010
TheNextWeb представляет европейские стартапы.
Announcing the finalists of The Next Web Paypal X Startup Rally 2010
ТехКранч вторит им: 25 Startups That Will Be Shaping The Next Web
Мы рассмотрим их вкратце, все 25 проектов:
Вот такие они, европейские стартапы! Мне несколько идей очень понравились!!
Announcing the finalists of The Next Web Paypal X Startup Rally 2010
ТехКранч вторит им: 25 Startups That Will Be Shaping The Next Web
Мы рассмотрим их вкратце, все 25 проектов:
- Tribe of Noise - коммьюнити, пытающееся соединить музыкантов и лейблы. А может, попытка взять часть функционала Last.FM и ILike.com и примешать что-то новое?
- Inbox2 - почта + социальные контакты + документы + календарь - и все в одном месте =)
- Fashiolista - что-то про моду, не разобрал =) Не мое
- MailSuite - почтовая система
- pipio - система для организации разговоров (conversations)
- Distimo - система аналитики по app store
- Twittercounter - система статистики по Твиттеру
- ecwid - российский проект. Позволяет прикрутить SaaS-hosted интернет-магазин для любого сайта за пару минут
- DoubleDutch - гео-социальноый проект. Позволяет пользователям включать в свою социальную активность гео-составляющую
- English Attack! - обучение англискому, entertainment-based метод
- Fits.me - примерочная интернет-комната для одежды
- Next Widgets - виджеты, вирусный маркетинг
- Feest.je - опять гео-социальный сервис
- 22tracks - музыкальный сервис. Позволяет пользователям открывать новых исполнителей, новые жанры и т.д. Что прикольно - не надо никакой регистрации. Сейчас, когда я это пишу - у меня как раз играет композиция из 22tracks
- Sogeo Сcompany - позволяет бизнесу строить коммьюнити потребителей на основе местоположения. В общем, еще один геосоциальный сервис
- Peecho - cloud printing as a serice. Вот так-то вот... =) Пошел относить свой лазерник на помойку =)
- PressDoc - быстрые и интерактивные онлайн пресс-релизы. Социальные медиа.
- next2news - рекламная платформа, размещающая рекламу в новостях. Но - только на голландском.
- Buildor - cloud-hosted ПО для создания сайтов, редактирования HTML/CSS
- submate - социальный сервис - узнай своих попутчиков по метро
- rapportive - социальная CRM-система, встроенная в GMail
- shutl - почти мгновенная доставка покупок из онлайн-магазинов. Хм, интересно!
- brainient - помогает паблишерам видео-контента зарабатывать путем приаттачивания ссылок на продукты, упомянутые в их видео-роликах. Тоже неплохо, имхо!
Вот такие они, европейские стартапы! Мне несколько идей очень понравились!!
Ярлыки:
money,
startup,
the next web
Twitter нашел свою бизнес-модель: promoted twits and more
На ТехКранче написали, что Твиттер приоткрывает детали своей бизес-модели: Twitter CEO Ev Williams: Revenue Is A Feature.
Рекламная платформа Твиттера называется Promoted Tweets. Она будет доступна каждому, у кого есть аккаунт на твиттере. Распределение прибыли будет 50/50 между рекламодателем и твиттерянином.
CEO Twitter Evan Williams говорит, что есть множество путей монетизировать трафик, особенно, когда его много. Мы знаем, что у Твиттера трафика не просто много, а очень много. Однако, в Твиттере хотят, чтобы их рекламный продукт был органической частью их сервиса. Promoted Tweets будут действовать также, как и обычные твиты, их можно будет ретвитить, отвечать на них, добавлять в закладки и т.п.
Сначала они будут оплачиваться cost-per-impression-базисе (CPM), но Твиттер обещает скоро ввести новую метрику - которая будет оценивать "резонанс" - и дальнейшая оплата таких твитов будет происходить на базе этой метрики. Резонансная метрика будет учитывать такие факторы, как то, как часто просматривается твит, добавляется в закладки, ретвитится и т.п. Если Твиттер соберяется изменять резонанс, то модель оплаты, видимо, очень скоро уйдет от классической CPM-модели.
Успех Promoted Tweets будет определяться тем, как пользователи воспримут их и насколько будут с ними взаимодействовать. Если они не будут восприниматься как твиты, то эта затея выродится просто в еще один вид встраиваемой рекламы.
Рекламная платформа Твиттера называется Promoted Tweets. Она будет доступна каждому, у кого есть аккаунт на твиттере. Распределение прибыли будет 50/50 между рекламодателем и твиттерянином.
CEO Twitter Evan Williams говорит, что есть множество путей монетизировать трафик, особенно, когда его много. Мы знаем, что у Твиттера трафика не просто много, а очень много. Однако, в Твиттере хотят, чтобы их рекламный продукт был органической частью их сервиса. Promoted Tweets будут действовать также, как и обычные твиты, их можно будет ретвитить, отвечать на них, добавлять в закладки и т.п.
Сначала они будут оплачиваться cost-per-impression-базисе (CPM), но Твиттер обещает скоро ввести новую метрику - которая будет оценивать "резонанс" - и дальнейшая оплата таких твитов будет происходить на базе этой метрики. Резонансная метрика будет учитывать такие факторы, как то, как часто просматривается твит, добавляется в закладки, ретвитится и т.п. Если Твиттер соберяется изменять резонанс, то модель оплаты, видимо, очень скоро уйдет от классической CPM-модели.
Успех Promoted Tweets будет определяться тем, как пользователи воспримут их и насколько будут с ними взаимодействовать. Если они не будут восприниматься как твиты, то эта затея выродится просто в еще один вид встраиваемой рекламы.
Ярлыки:
twitter
среда, 14 апреля 2010 г.
Студенческий день Яндекса
Не могу не записать: Студенческий день Яндекса. Много хороших презентаций!!
Ярлыки:
search engines,
yandex
Настройка Google App Engine Launcher
Поговорим о настройках GAE лончера. Лончер используется для того, чтобы запускать GAE-приложения на локальной машине. При запуске, по умолчанию, лончер привязывается на адрес локалхоста, т.е. на 127.0.0.1 - так называемый loopback. А что, если нам надо его привязать к внешнему адресу (в нашей локальной сети), например, на 192.168.1.100 ?
Это делается очень просто. Выделяем в лончере приложение, которое хотим привязать к внешнему IP, нажимаем Ctrl+I (или выбираем пункт меню Edit->Application Settings). Открывается окошко с настройками.

В блок Extra Command Line Flags записываем следующее:
--address=192.168.1.100
нажимаем ОК - и вуаля - приложение привязано к IP 192.168.1.100.
Единственно, что надо добавить - так это то, что эти настройки надо делать при выключенном приложении.
Помимо флага --address есть еще множество других настроек:
Прочитать про это можно также здесь: Google App Engine Launcher Options
Это делается очень просто. Выделяем в лончере приложение, которое хотим привязать к внешнему IP, нажимаем Ctrl+I (или выбираем пункт меню Edit->Application Settings). Открывается окошко с настройками.

В блок Extra Command Line Flags записываем следующее:
--address=192.168.1.100
нажимаем ОК - и вуаля - приложение привязано к IP 192.168.1.100.
Единственно, что надо добавить - так это то, что эти настройки надо делать при выключенном приложении.
Помимо флага --address есть еще множество других настроек:
--help, -h View this helpful message.
--debug, -d Use debug logging. (Default false)
--clear_datastore, -c Clear the Datastore on startup.
--address=ADDRESS, -a Server binding address
--port=PORT, -p PORT Port for the server to run on.
--datastore_path=PATH Path to use for storing Datastore
file stub data
--history_path=PATH Path to use for storing Datastore
history
--require_indexes Disallows queries requiring composite
indexes not defined in index.yaml.
--smtp_host=HOSTNAME SMTP host to send test mail to.
--smtp_port=PORT SMTP port to send test mail to.
--smtp_user=USER SMTP user to connect as.
--smtp_password=PASSWORD Password for SMTP server.
--enable_sendmail Enable sendmail when SMTP is not
configured.
--show_mail_body Log the body of emails in mail stub.
--auth_domain Authorization domain
Прочитать про это можно также здесь: Google App Engine Launcher Options
Ярлыки:
google app engine
пятница, 9 апреля 2010 г.
Захват видео во флеше
Рассмотрим, как показывать видео, захваченное с веб-камеры пользователя во флешке.
Перейдем сразу к коду.
Файл camtest_min.mxml:
Скомпилируем код следующей командой:
%SDKDIR%\bin\mxmlc -optimize=true -o camtest_min.swf camtest_min.mxml
После этого, открыв файл в браузере, получим изображение с камеры.
Во флешке вылезет окошечко с запросом на разрешение доступа к микрофону и камере.
Это окошко появляется в момент, когда камера аттачится к VideoDisplay.
Чуть более подробно можно посмотреть по ссылке Detecting changes in a camera’s activity and status in a Flex VideoDisplay control
Перейдем сразу к коду.
Файл camtest_min.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal"
verticalAlign="middle"
backgroundColor="white">
<mx:Script>
<![CDATA[
private function videoDisplay_creationComplete():void {
trace('[camtest.videoDisplay_creationComplete]');
var camera:Camera = Camera.getCamera();
if (camera) {
trace('[camtest.videoDisplay_creationComplete] camera is OK');
videoDisplay.attachCamera(camera);
camera.addEventListener(ActivityEvent.ACTIVITY, camera_activity);
camera.addEventListener(StatusEvent.STATUS, camera_status);
} else {
trace('[camtest.videoDisplay_creationComplete] perhaps there is no camera on this computer');
}
}
private function camera_activity(evt:ActivityEvent):void {
trace('[camtest.camera_activity], evt.type='+evt.type+', evt.activating='+evt.activating);
}
private function camera_status(evt:StatusEvent):void {
trace('[camtest.camera_status], evt.code='+evt.code);
switch (evt.code) {
case "Camera.Muted":
// do smth
break;
case "Camera.Unmuted":
// do smth
break;
}
}
]]>
</mx:Script>
<mx:VideoDisplay id="videoDisplay"
creationComplete="videoDisplay_creationComplete();"
width="320"
height="240" />
</mx:Application>
Скомпилируем код следующей командой:
%SDKDIR%\bin\mxmlc -optimize=true -o camtest_min.swf camtest_min.mxml
После этого, открыв файл в браузере, получим изображение с камеры.
Во флешке вылезет окошечко с запросом на разрешение доступа к микрофону и камере.
Это окошко появляется в момент, когда камера аттачится к VideoDisplay.
Чуть более подробно можно посмотреть по ссылке Detecting changes in a camera’s activity and status in a Flex VideoDisplay control
Подписаться на:
Сообщения (Atom)