Категорія: Gotchas

 

Тимчасовий обхід обмеження довжини varchar

В одному з моїх поточних проектів у процесі розробки процесу імпорту великих об’ємів даних виникла задача ефективно (швидко) обійти обмеження довжини varchar полів у базі даних. Фактично, ми готові були пожертвувати частиною даних задля збереження швидкості роботи.

Річ у тім, що MySQL за умовчанням не дозволяє запхати в поле varchar рядок довший за наперед визначену розмірність.

Але це можна обійти скинувши налаштування @@sql_mode.

В якості демонстрації принципу наведу шмат коду, коментарі мають все пояснити.

<!---
CREATE TABLE IF NOT EXISTS contacts (
  contactId int(10) unsigned NOT NULL AUTO_INCREMENT,
  salutation varchar(5) DEFAULT NULL,
  firstname varchar(255) DEFAULT NULL,
  PRIMARY KEY (contactId)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
 --->


<cfset local = {} />
<cfset local.value = "Doctor" />


<!--- save the current SQL mode --->
<cfquery datasource="my_test_dsn" name="local.getSqlMode">
    select @@sql_mode as sqlmode
</cfquery>

<!--- reset the SQL mode --->
<cfquery datasource="my_test_dsn" result="local.resetSqlMode">
    set sql_mode = ''
</cfquery>


<!--- this should work fine --->
<cfquery datasource="my_test_dsn" result="local.pushContact">
    INSERT INTO contacts (salutation, firstname) VALUES ('#local.value#', '#local.value#')
</cfquery>


<!--- restore the SQL mode --->
<cfquery datasource="my_test_dsn" result="local.revertSqlMode">
    set sql_mode = '#local.getSqlMode.sqlmode#'
</cfquery>


<!--- this should fail --->
<cfquery datasource="my_test_dsn" result="local.pushContact">
    INSERT INTO contacts (salutation, firstname) VALUES ('#local.value#', '#local.value#')
</cfquery>


<cfdump var="#local#">

Автор: Сергій Галашин | Опубліковано: 14.09.2010 о 15:51 | Категорії: Gotchas - MySQL -

 

Самопідписаний SSL сертифікат в Railo

Нещодавно зіткнувся з доволі відомою проблемою для CFML-розробників: CFHTTP відмовляється працювати з HTTPS-сайтом якщо сертифікат є само-підписаним, або не засвідченим авторизованим центром. Більше того, у мене сертифікат був у порядку, оглядачі чудово його сприймали, але не Railo.

Стандартним рішенням є додавання відкритої частини сертифікату до сховища ключів (keystore) JVM, котру використовує ColdFusion/Railo.

Але ця процедура може виявитися доволі хитрою, коли мова йде про Railo.

 

Спочатку я спробував піти "правильним" шляхом, та скористатися вбудованими функціями якраз для цього діла:

SSLCertificateList("hostname") чудово показала мені список сертифікатів (а він там був один) потрібного сайту.

SSLCertificateInstall("hostname") без жодних претензій його встановила.

Але ж дулі! Все одно продовжив бачити помилку sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

 

Тоді я взявся за консоль. Спочатку я перевірив чи спрацювали функції:

$ cd ~/webapps/xxxxx/WEB-INF/railo/security/
$ keytool -list -keystore cacerts

Потрібний сертифікат був у списку. Підказка: за умовчанням пароль для keytool є "changeit" (без лапок, звісно).

Про всяк випадок я спробував перевстановити його вручну. Для цього експортував .crt файл сертифікату сайту за допомогою оглядача (Firefox, в моєму випадку) та замінив запис:

$ keytool -delete -alias myalias -keystore cacerts
$ keytool -import -alias myalias -keystore cacerts -file /home/zzz/xxxxx.crt
$ keytool -list -keystore cacerts

Після цього перезапустив Railo та... не отримав нічого.

 

Наступна спроба зареєструвати сертифікат аналогічним способом була пов’язана з JVM, для Ubuntu та JVM від Sun шлях до них виглядає десь так:

/usr/lib/jvm/java-6-sun/jre/lib/security/

Вона теж виявилася невдалою, хоча для Adobe ColdFusion цей спосіб зазвичай працює.

 

Насамкінець я згадав, що Railo має ще кореневий контекст, в моєму випадку це тека

/opt/railo/webapps/ROOT/WEB-INF/railo/security/

Повторивши імпорт ще тут та перезапустивши Railo все запрацювало!

 

Автор: Сергій Галашин | Опубліковано: 01.09.2010 о 22:21 | Категорії: Gotchas - Java - Railo - Security -

 

Ошибка инсталлятора Coldfusion 8 в Centos 5

Проблема - при инсталляции не создается коннектор для Apache. Вполне вероятно, что это можно наблюдать не только на CentOS.

Нужно доустановить пакет http-devel, и после этого не постеснятся скомпилировать коннектор вручную, подправив и запустив этот скрипт:

# cd /opt/coldfusion8/bin/connectors
# ./apache_connector.sh

Также может помочь GUI-тулза /opt/coldfusion8/runtime/bin/wsconfig

Автор: Родион Быков | Опубліковано: 27.08.2010 о 15:15 | Категорії: ColdFusion 8 - Gotchas -

 

Coldfusion 9 и проблема с Apache Virtualhost

После "чистой" установки Coldfusion 9 возникла странная проблема. Виртуальные хосты Apache 2.2 не работали, и документы *.cfm отдавались только по прямой ссылке в текстовом виде. То есть казалось, что проблемы две - неработающая Coldfusion и неработающие хосты. Однако, оказалось что инсталлятор не добавил handler, и обе проблемы решились одновременно, исправлением httpd.conf - в строчке AddHandler надо добавить .cfm и .cfc

# JRun Settings
LoadModule jrun_module "C:/ColdFusion9/runtime/lib/wsconfig/2/mod_jrun22.so"
<IfModule mod_jrun22.c>
    JRunConfig Verbose false
    JRunConfig Apialloc false
    JRunConfig Ignoresuffixmap false
    JRunConfig Serverstore "C:/ColdFusion9/runtime/lib/wsconfig/2/jrunserver.store"
    JRunConfig Bootstrap 127.0.0.1:51800
    AddHandler jrun-handler .jsp .jws .cfm .cfc
</IfModule>

Не забыть про DirectoryIndex:

<IfModule dir_module>
     DirectoryIndex index.cfm index.html index.htm
</IfModule>

Виртуал хосты соответственно:

NameVirtualHost *:80
<VirtualHost *:80>
   DocumentRoot "C:/inetpub/wwwroot/domain1"
   ServerName domain1
</VirtualHost>
<VirtualHost *:80>
   DocumentRoot "C:/inetpub/wwwroot/domain2"
   ServerName domain2
</VirtualHost>

Автор: Родион Быков | Опубліковано: 21.05.2010 о 12:52 | Категорії: Apache - ColdFusion 9 - Gotchas -

 

Ошибка Flash Remoting при использовнии Coldfusion mappings

Допустим есть CFC который обслуживает Flex-приложение. Для этого используется Flex gateway, который есть в любой инсталляции Coldfusion 8 по умолчанию. Однако можно наступить на грабельки, если CFC наследует или использует другой CFC:

<cfcomponent displayname = "Component to serve data to Flex Application"
             extends ="cfcRoot.services.CommonService">

Ничего особенного, но в нашем случае, cfcRoot - это mapping, заданный в Coldfusion Administrator. При вызове метода этого CFC, Flex скорее всего выдаст ошибку

message = Unable to invoke CFC - Could not find the ColdFusion Component or Interface cfcRoot.services.CommonService.
details = Ensure that the name is correct and that the component or interface exists.

Ошибка значит ровно то, что написано - Coldfusion не может найти компонент, указанный в клаузе "extends".

"Виноваты" в этом настройки Flex gateway. По-умолчанию, Coldfusion не будет проверять маппинги при обращении к CFC через Flash remoting. За это отвечает клауза <destination id="ColdFusion"> в файле C:\ColdFusion8\wwwroot\WEB-INF\flex\remoting-config.xml

<!-- Use the ColdFusion mappings to find CFCs, by default only CFC files under your webroot can be found. -->
<use-mappings>false</use-mappings>

Достаточно изменить значение на true и перезапустить Coldfusion.

Автор: Родион Быков | Опубліковано: 10.12.2009 о 11:24 | Категорії: Flash - Flex - Gotchas -

 

Java альтернатива cfexecute

Марк Дрю розповів про зручну заміну cfexecute. Залишимо його приклад для коміту в репозиторій Git в якості пам'ятки для розробників без Java-досвіду:

<!--- since we have made modifications to the files, we need to commit them in git --->
<cfscript>
    // first of we set the command to call
    cmd1 = "git add TODO.txt";
    cmd2 = "git commit -m 'autobackup'";
    // the environment variable is empty
    envp = arraynew(1);
    // and we want to run from a given "root"
    path = "/Volumes/iDisk/Documents/TODO";
    dir = createobject("java", "java.io.File").init(path);
    // get the java runtime object
    rt = createobject("java", "java.lang.Runtime").getRuntime();
    // and make the exec call to run the command
rt.exec(cmd1, envp, dir);
rt.exec(cmd2, envp, dir);
</cfscript>

Автор: Сергій Галашин | Опубліковано: 27.11.2009 о 07:56 | Категорії: Gotchas - Java -

 

Деякі відмінності між Verity та Solr

Реймонд Кемден в формі конспекту розповів про ключові відмінності між новим пошуковим двигуном Solr для CF9 та його попередником -- Verity.

Серед основних можна відмітити значне покращення швидкодії, зникнення обмежень на розмір індексу, уніфікацію пошуку за регистром -- завжди в нижньому, зміни в синтаксисі запитів (+/- замість AND/NOT), заборона використання шаблонів (?/*) на початку запиту, відмова від previousCriteria -- але QoQ нікуди не дівається.

Трохи детальніше про ці та інші зміни в замітці Кемдена.

Автор: Сергій Галашин | Опубліковано: 31.10.2009 о 19:11 | Категорії: ColdFusion 8 - ColdFusion 9 - Gotchas -

 

Що обрати для Client Storage: Registry чи Datasource

Марк Кругер докладно розповів про те, чому потрібно запобігати використанню реєстру для зберігання клієнтських змінних (client variables).

Він навів приклад, коли за кілька місяців (за умовчанням 90 днів) Adobe ColdFusion починає періодично очищувати реєстр (знову-таки, за умовчанням кожні 67 хвилин), що призводить до несподіваних "залипань" сервера.

Цікаво, що ця проблема стосується й Linux, де реєстр просто емулюється в текстовому файлі (/coldfusion8/registry/cf.registry).

Він слушно зауважив про те, що напевно запобігти використанню цих змінних дуже складно, навіть якщо розробник запевняє, що не користується ними.

Тож він пропонує використати окрему базу (MySQL чи SQL Server цілком підійдуть) та відповідне джерело даних (datasource) для зберігання клієнтських змінних -- з прикладами, та наводить кілька порад щодо ефективного використання цьго методу.

Насамкінець він розповідає про кілька проблем, що можуть спіткати на шляху впровадження цієї оптимізації, особливо коли це стосується налаштувань вже робочого серверу.

Про все це докладно та з прикладами читайте в дописі Марка.

 

 

Автор: Сергій Галашин | Опубліковано: 28.10.2009 о 11:11 | Категорії: Blogs - ColdFusion 8 - ColdFusion 9 - Gotchas - Performance -

 

Підхід до розгортання сайту на базі Fusebox 5

В нетрях обговорення груп Railo виявив пару повідомлень, інформацію з котрих варто зберегти на майбутнє. В них наводиться спосіб оновлень живого сайту на базі Fusebox 5.

Основною проблемою, що треба вирішити, це генерація parsed файлів при одночасному доступі кількох (багатьох) користувачів. Це є відомим недоліком FB, котрий поки що не було остаточно виправлено. Суть його в тому, що при конкурентному доступі FB може записати "криві" файли (наприклад, недописані, коли <cfif> не закривається), через які весь додаток перестає працювати, видаючи незрозумілі й кожного разу різні помилки CFML синтаксису.

 

Тут є дві речі, що варто пам'ятати.

 

1. Необхідно завжди вмикати production mode на живому сайті. Незважаючи на очевидність кроку, це вельми розповсюджена помилка. Бо в development режимах FB генерує ті чи інші файли, що значно підвищує вірогідність виникнення помилок. Не кажучи вже про те, що сповільнює роботу сайту.

 

2. Варто тримати три робочі копії проекту.

Перша -- повноцінна розробницька версія, з відповідним development режимом, типово локально у розробника.

Друга -- живий сайт, з production режимом та всіма відповідними налаштуваннями.

І нарешті третя копія, призначення тільки для розгортання (deployment). Вона розміщується окремо від основного сайту (на тому самому сервері) та призначена для безпечного генерування parsed файлів (для великих проектів може займати кілька хвилин), котрі потім гуртом копіюються прямо на живо. Цю операцію варто повторювати при кожному оновленні, принаймні коли змінюються файли, що знаходяться під контролем Fusebox'у.

У випадку зміни ланцюжків (circuits) може потребуватися запустити основний сайт з fusebox.load, щоб він їх "підхопив".

 

На щастя, цей процес цілком можна автоматизувати, наприклад за допомогою Ant.

 

Примітка для користувачів Railo: deployment та production копії варто тримати ізольованими в різних веб-контекстах, хоча саме ядро Fusebox може бути те саме, достатньо використати мапінги (mapping) для контекстів.

 

 

Автор: Сергій Галашин | Опубліковано: 06.10.2009 о 06:23 | Категорії: Fusebox - Gotchas - Railo -

 

Про деякі особливості Application.cfc

Не всі розробники задумуються над тим, що Application.cfc це не тільки Application, але й повноцінна CFC. Використання її саме у якості компоненти дає кілька цікавих можливостей.

Наприклад, розглянемо таку просту компоненту:

<cfcomponent output="false">

<cfset this.name = "application_introspect" />
<cfset this.foo = "bar" />

<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfargument name="thePage" type="string" required="true">
<cfset application.thePage = arguments.thePage />
<cfreturn true />
</cffunction>

</cfcomponent>

 

А тепер спробуємо використати її.

<cfdump var="#Application#" >

<p>&nbsp;</p>

<cfset test = CreateObject("component", "Application") />
<!--- CF9 way
<cfset test= new Application() />
--->
<cfdump var="#test#">

<cfset test.onRequestStart("introspect.cfm") />

<p>&nbsp;</p>

<cfdump var="#Application#">

 

Таким нехитрим способом можна робити дві речі:

  1. Подивитися що всередині об'єкту Application (на прикладі this.foo).

  2. Зручно маніпулювати Application scope.

 

Результат роботи вищевказаного коду виглядатиме так:

 

Автор: Сергій Галашин | Опубліковано: 06.09.2009 о 09:09 | Категорії: CFML - ColdFusion 8 - Gotchas -

 

Підміна MIME типу при завантаженні .cfm файлів на сервер

Днями прокотилася хвиля серйозних порушень роботи сайтів та навіть цілих ColdFusion серверів, пов'язана з використанням вразливості, коли підміна MIME типу завантажуваного файлу дозволяла залити .cfm скрипт та виконати його.

Ось простий приклад як це можна зробити:

<cfhttp url="http://target.example.com/upload" method="post">
 <cfhttpparam file="#ExpandPath("badstuff.cfm")#"
  mimetype="image/gif"
  type="file"
  name="photo">
</cfhttp>

Така проста конструкція легко дозволяє обійти вбудовану перевірку типу:

<cffile action="upload"
  filefield="photo"
  accept="image/gif,image/jpeg"
  destination="#ExpandPath("./photos/")#">

Приклади було взято з посту Піта Фрейтаґа (Pete Freitag), в якому він наводить рекомендації щодо захисту від подібних атак.

Зокрема, можна використати вбудовані функції IsImageFile("path") (з урахуванням вже описаної проблеми) та IsPDFFile("path"), використовувати окремий сервер (простіше кажучи, окремий домен - скажімо з nginx - для швидкодії) для статичного вмісту (як то Amazon S3), користуватися можливостями Sandboxing (якщо у вас CF Enterise), відключати можливість виконання скриптів для тек завантаження та іншими методиками.

Ці та інші поради описані у вищевказаному повідомленні, також варто звернути увагу на коментарі до нього, там теж є слушні поради.

Також варто звернути увагу на аналогічне повідомлення Брента Фрая (Brent Frye), котрий зазнав серйозних неприємностей через описану проблему, тому теж уклав список порад для її обходу.

 

Автор: Сергій Галашин | Опубліковано: 01.07.2009 о 05:34 | Категорії: Blogs - Gotchas - Security -

 

Подводные камни remote-методов

Организовать удаленный доступ к данным в Coldfusion - дело достаточно простое. Любой метод Coldfusion-компонента может вызываться удаленно, достаточно лишь поставить модификатор доступа access="remote", вот простой пример:

  <cfcomponent displayname="myservice" hint="Service" output="false">
    
    <cffunction name="getStructure" access="remote" output="false" returntype="Struct">
        <cfset struct = StructNew() />
        <cfset struct["id"] = 213 />
        <cfset struct.refID = 321231 />
        <cfset struct["someName"] = "Foo Bar" />
        <cfreturn struct />
    </cffunction>

    <cffunction name="getQueryObject" access="remote" output="false" returntype="Query">
        <cfquery datasource="test" name="qry">
            SELECT id, someName, refID FROM test
        </cfquery>       
        <cfreturn qry />
    </cffunction>

</cfcomponent>

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

- имена полей в объектах query возвращаются в UPPERCASE при вызове метода через SOAP;

Test case for query exposed with webservice


- имена полей в объектах query возвращаются точно так как написано в коде, если метод вызывается через Flash Remoting (осторожно, флешеры!). При этом название поля в БД не имеет значения. Если поле в БД называется id, а программист в коде SQL запроса выбрал его как Id, во Flash Remoting отразится именно так. Как известно, ActionScript различает case символов, а значит могут быть проблемы.

Test case for query exposed with flash remoting

- имена ключей в структурах возвращаются в UPPERCASE, если поле задано как struct.fieldName. При этом, case сохраняется в точности как задан, если поле задано как struct["fieldName"]. Сказанное справедливо для структур, возвращенных и через Web Service и через Flash Remoting.

Test case for structure

Автор: Родион Быков | Опубліковано: 30.05.2009 о 00:58 | Категорії: Gotchas -

 

Кириличні заголовки постів у MangoBlog

З переїздом на Mango у нас відразу виникла проблема: при створенні токенів (імен) для URL постів на базі заголовку видалялись кириличні символи. Це відбувалось тому, що блоґ намагався зробити безпечні посилання, а в таких знаходилося місце тільки літерам латинки, цифрам та дефісам.

Наприклад, спробувавши створити такий пост:

mango_tokens_1_preface

Ми отримували не дуже гарне посилання на цей пост:

mango_tokens_2_problem

Найбільш серйозною проблемою була втрата унікальності URL'ів, коли "Мій пост про MySQL" мав би майже таке саме посилання, що й "Пост не тільки про MySQL". Майже, бо блоґ додав би якесь випадкове число для запобігання співпадінь.

Почухавши потилицю, я вирішив виправити це діло. Півгодини копирсання в коді дали зрозуміти, що найбільш безболісним буде шлях транслітерації заголовку до його "чистки".


Читати далі...
Автор: Сергій Галашин | Опубліковано: 17.05.2009 о 18:39 | Категорії: Gotchas - Mango Blog - Unicode -