Шаг 30 - "Разрешение монитора" выворачиваем на изнанку

Добрый день Андрей!

Случайно вышел на Ваш сайт. По внешнему виду он конечно не шедевр
дизайнерской мысли, но зато шедевр по содержанию. Возможно программеры
профи и посмеялись надо мной, что мол я так, но для ламера/новичка Ваш
сайт действительно находка. Классный подход, редко такое встречается в
рунете, а по моему так Ваш сайт в единственном экземпляре, такой
дотупный и понятный. Давно задумывался о передаче разрешение
монитора через CGI на сервер, но ничего немог сообразить, а тут
бац...:) и Ваш "ШАГ"
Шаг 26 - Передаем разрешение монитора в CGI скрипт. (17.07.2000 - 3.3 Kb)
Я обрадовался и начал его применять, но произошёл затык у меня. У Вас
расмотрен случай когда инфа о разрешении передаётся на сервак через
QUERY_STRING для какого либо скрипта. В скриптах перл или РНР я к
сожалению нулевой, а хотел применить Ваш подход к SSI, но ничего не
получилось.
Точнее получилась передача по клику и вставка соответсвенная
делается(работает), а вот передать с помощью тега <img ...> инфу о
разрешении для выполнении SSI не получилось.

Вот это работает у меня.
<script language=javascript1.2>
document.write("<a href=/ho/ho.html?",screen.width+'x'+
	screen.height,">Click</a>");
</script>

А вот это не работает.
<script language=javascript1.2>
document.write("<img src="/menu/services_off.gif?",screen.width+
	'x'+screen.height,"" width="178" height="27" border="0">")
</script>

Видимо что то я неправильно сделал :) естественно, еслиб правильно, то
работало бы :)

Подскажите пожалуйста как подправить эту конструкцию, чтобы SSI АПАЧИ
нормально получил и использовал инфу об разрешении и выдал бы
соответствующую страницу?
  
С уважением, Дмитрий

Во-первых, что мне сразу не нравится... Чтобы посмотреть работоспособность вашего скрипта мне пришлось на его эскейпить, т.е. все кавычки переводить из " в \". Либо это он у вас в таком виде, либо это Вы его в таком виде привели, но не в этом дело. Я прошу Вас всех забыть про кавычки... Мало того, что Вы тратите свое драгоценное время на такую не интересную операцию, как расставление кавычек, Вы еще снабжаете браузер посетителя ненужной ему информацией. Каждая такая кавычка стоит пользователю 2 байта + N команд процессора для парсинга и обработки. Вы тратите и свои и чужые ресурсы... Боритесь за чистоту кода и интернета в целом %))

Теперь после небольшой пропаганды приступим к вопросу...

Снова на лицо путаница в технологиях и их возможностях. Действительно в SSI можно передать разрешение монитора первым способом, но Вы никогда не передадите в SSI(т.е. в HTML) разрешение через картинку. Поймите процесс. Когда Вы запрашиваете страницу HTML, то сервер начинает ее обрабатывать в зависимости от своих настроек. Изображения же сервер никогда не обрабатывает, он их просто считывает и глупо передает. Теперь же в HTML Вы можете применить SSI, а как Вы эту технологию примените к картинке ? Неужели в бинарные данные будете вставлять какие-то команды ? Так нельзя... Поэтому забудьте про SSI в катринках и сегодня я могу даже сказать больше: забудьте про SSI вообще. Да это хорошая технология, но она устарела, причем очень сильно. Конечно ее все применяют, и возможно будут еще долго применять, но она все же уже на таких простых задачках как "текущая" не может обеспечить грамотного решения.

Зато такую задачу может решить CGI. И зря Вы этого пугаетесь. Зря Вы не знаете Perl, PHP или C. Сегодня без знания хотя бы одного из этих языков Вы ничего хорошего сделать не сможете.

Все решение данной задачи сводится к тому, чтобы в зависимости от одной или двух цифр вывести какие-то данные. Причем данные любые, будь-то текст или бинарные.

Давайте решим эту задачу через CGI причем сделаем это несколькими способами.

Для начала на любимом C:

#include <stdio.h>
#include <stdlib.h>

int sendfile(char *name){
	FILE *f_in=NULL;
	char b;
	f_in=fopen(name,"rb");
	if (f_in==NULL) return -1; //ERROR !!!
	while (!feof(f_in)){
		fread(&b,1,1,f_in);
		fwrite(&b,1,1,stdout);
	};
	fclose(f_in);
	return 0;
};

int main(){
	char *query_string;
	char *request_method;
	char *file_name=NULL;

	request_method=getenv("REQUEST_METHOD");
	if (request_method==NULL) return 0;
	if (strcmp(request_method,"GET")==0){
		fprintf(stdout,"Content-type: image/gif\n\n");
		query_string=getenv("QUERY_STRING");
		if (strlen(query_string)>0){
			file_name=(char *)malloc(strlen(query_string)+5);
			sprintf(file_name,"%s.gif",query_string);
			if (sendfile(file_name)!=0){
				sendfile("error.gif");
			};
			free(file_name);
		} else {
			sendfile("error.gif");
		};
	} else {
		fprintf(stdout,
			"Content-type: text/plain\n\n"
			"Error ! Mda... I know only GET method..."
		);
	};
	fflush(stdout);
	return 0;
};

Код мне кажется максимально прост. Процедура sendfile() посылает в stdout указанный файл. Главная программа получает переменную QUERY_STRING и строит имя файла. Потом пытается послать его. Если такого файла не существует или произошла какая-то ошибка, то она посылает файл error.gif, который по определению должен существовать. Вот и вся программка. А главное в ней это строка:

fprintf(stdout,"Content-type: image/gif\n\n");

Именно по этому заголовку браузер определяет, что ему передают не текстовое содержимое, а графическое в формате GIF.

Вызывать этот скрипт просто, и думаю об этом говорить уже не надо, однако:

<img src=test.cgi?1024x768>

Именно такую строку должен генерить Ваш код на JavaScript. Скрипт же, в свою очередь, будет пытаться послать файл 1024x768.gif.

Теперь аналогичная программка на PHP:

<?php
header("Content-type: image/gif\n\n");
$filename = getenv("QUERY_STRING").".gif";
$fd = fopen ($filename, "r");
if ($fd!=0){
	$contents = fread($fd, filesize($filename));
	fclose ($fd);
	echo $contents;
};
?>

На PHP получился код чуть проще, но он не умеет обрабатывать ошибки, например, когда файл не существует, то интерпретатор PHP выводит Warning: No such file or directory. Отключить это явление скорее всего можно поковырявшись в настройках, но не у всех из нас есть доступ к ним, к тому же выключение сообщений может повлиять на другие важные сообщения не относящиеся к файлам.

Общий смысл я думаю понятен. Выводится заголовок Content-type: image/gif\n\n, а затем уже тот файл, который зависит от того, что у нас в QUERY_STRING.

Ну, а теперь самое интересное !!! Настолько ли непригодна технология SSI для нашей задачи ? Конечно она не пригодна, но визтуозы своего дела могут все... Кстати эту задачку можно расценить как "просунуть слона через игольное ушко". Кто-то скажет, что это не возможно, а кто-то просто слона разрежет %))) Вот я и разрезал...

Что нам мешает послать изображение браузеру ? Ответ был дан ранее и я акцентировал на этом внимание. Конечно это заголовок. Заголовок для HTML выдается таким Content-type: text/html\n\n. Но нам это совершенно не годится.

Давайте создадим новый тип файлов со своим заголовком в Apache. Я этот тип назвал sgif, что значит SSI-GIF :)). Создать подобный тип можно в главном httpd.conf файле или же для конкретной директории с помощью файла .htaccess. Второй способ, скажу я Вам, более пригоден для нашей задачи, потому что он носит локальный характер и действует только на одну директорию. Если у нас есть специальная директория, то мы можем даже для нее определить тип файлов gif.

Создаем файл .htaccess и пишем в него:

AddType image/gif .sgif
AddHandler server-parsed .sgif

Вторая строка, как видите, как раз и говорит серверу о том, что эти файлы будут использовать технологию SSI.

Ну, а теперь создаем файл test.sgif и пишем в него:

<!--#include file="$QUERY_STRING.gif" -->

Теперь изображение <img src=test.sgif?1024x768> будет грузить соответствующий файл.

Вот вам и SSI %). Хехехе, в очередной доказано, что "неразрешимых задач нет". SSI, PHP - все это конечно круто, но нет ничего лучше самого C++. Поэтому делайте выводы...


Предыдущий Шаг | Оглавление
Автор Кузин Андрей - 22.06.2001