ADODB.Stream запись бинарника, JScript only!
От: EugeNet.Spb  
Дата: 08.06.04 17:00
Оценка:
Тема измусолена, но все-же никто не смог пока записать бинарник из JScript. Правда есть 1 гуру- он смог (http://rsdn.ru/Forum/Message.aspx?mid=670145&only=1
Автор: Andir
Дата: 08.06.04
), но только в UNICODE. Есть предложения как тип изменить?
Проблема именно в ADODB.Recordset, а не стриме, стрим уже получает юникодовую строку...

Собака зарылась в Fields.Append или rs.Fields(0).Type, но я вроде все перебрал- не получается.
Пробовал перебирать DataTypeEnum и FieldAttributeEnum — ничего пока.
в FieldAttributeEnum вообще интересно- есть только Long Binary (adFldLong), а просто бинари- нет.
как меняю- stream.Write ошибается, потому что переменная уже другого типа.

var rs = new ActiveXObject("ADODB.Recordset");
var stream = new ActiveXObject("ADODB.Stream");
var string = "test";

rs.Fields.Append( "test", /* adVarBinary */ 128, /* Size of field */ 512, /* Allow AppendChunk and GetChunk */ 0x80 );
//rs.Fields(0).Type = 128;
rs.Open();
rs.AddNew();
rs.Fields( 'test' ).AppendChunk( string );
rs.Update();
rs.MoveFirst();
binArray = rs( 'test' ).GetChunk( 512 );
rs.Close();

//stream.Charset = 'ASCII';
stream.Type = 1;
stream.Open();
stream.Write( binArray );
stream.SaveToFile( 'd:\\sdfsdf.txt' );
stream.Close();

Реально 3 дня искал везде- в мире все либо VBScript советуют (у меня есть рабочий пример, но я JS хочу), либо вообще не понимают проблемы.
Re: ADODB.Stream запись бинарника, JScript only!
От: Andir Россия
Дата: 09.06.04 01:59
Оценка:
Здравствуйте, EugeNet.Spb, Вы писали:

Вся твоя проблема не в стриме, а в том как ты получаешь бинарные данные. Приводи код.

P.S. Использую форматирующие теги в форуме [java]Код здесь[/java]

C Уважением, Andir!
<< using(Rsdn@Home 1.1.4 beta 2){/* Работаем */} >>
Re: ADODB.Stream запись бинарника, JScript only!
От: Andir Россия
Дата: 09.06.04 01:59
Оценка:
Здравствуйте, EugeNet.Spb, Вы писали:

ES>Проблема именно в ADODB.Recordset, а не стриме, стрим уже получает юникодовую строку...


Простейшая проверка показывает, что Recordset прекрасно работает с бинарными данными:
// Читаем бинарный файл
var stream = new ActiveXObject("ADODB.Stream");
stream.Type = 1;

stream.Open();
stream.LoadFromFile("c:\\readtest.exe");

stream.Position = 0;

var binData = stream.Read();

stream.Close();

// Делаем переброс в рекодсет и обратно ...
// Просто так :) для теста, а вдруг?
var bufferSize = 100000; // Размер буфера птичка напела :))

var rs = new ActiveXObject("ADODB.Recordset");

rs.Fields.Append("test", 204, bufferSize, 0x80);
rs.Open();

rs.AddNew();
rs.Fields("test").AppendChunk(binData);
rs.Update();

rs.MoveFirst();

var binArray = rs("test").GetChunk(bufferSize);

rs.Close();

// Сохраняем остатки
var stream = new ActiveXObject("ADODB.Stream");
stream.Type = 1;

stream.Open();
stream.Write(binArray);

stream.Flush();
stream.Position = 0;

stream.SaveToFile("c:\\writetest.exe", 2);

stream.Close();


С Уважением, Andir!
<< using(Rsdn@Home 1.1.4 beta 2){/* Работаем */} >>
Re[2]: ADODB.Stream запись бинарника, JScript only!
От: EugeNet.Spb  
Дата: 09.06.04 08:37
Оценка:
A>// Читаем бинарный файл

Ставлю проблему чётко:
Мне не нужно копировать бинарный поток, мне нужно создать его (внедрить exe/png в html).

В первой моей мессаге твой пример- он сохраняет строку как бинарные данные, но в UNICODE, а нужен 1-байтные тип.

Мне нужно генерить бинарные данные через мою простенькую функцию:

hex2str( 'D5A90000300000004000000FFF' );
которая возвращяет бинарную строку (String.fromCharCode);

Так-то понятно, что читаем стрим (не юникодовый), так он и сохраняется не юникодово, а вот сгенерить стрин скриптово (не из внешних источников) и сохранить в НЕюникоде- вот проблема.
Re[3]: ADODB.Stream запись бинарника, JScript only!
От: Andir Россия
Дата: 09.06.04 23:18
Оценка:
Здравствуйте, EugeNet.Spb, Вы писали:

ES>Мне нужно генерить бинарные данные через мою простенькую функцию:


ES>hex2str( 'D5A90000300000004000000FFF' );

ES>которая возвращяет бинарную строку (String.fromCharCode);

Всё понял. Вся проблема не в стриме, ещё раз тебе напомню, а в строках. В JScript все строки по умолчанию в Unicode.
Получаем задачу: Имея некоторую бинарную строку записанную в Unicode нужно преобразовать в однобайтную кодировку и сохранить как бинарный файл.
Последовательность действий такая:
1) Получить бинарную строку (это ты делаешь сам).
2) Преобразовать строку к однобайтной кодировке
3) Сохранить преобразование.

Получаем следующий вариант.

var binString = ""; // Некоторая бинарная строка, ты её сам получаешь.

var outStreamW = new ActiveXObject("ADODB.Stream"); // Текстовый поток с кодировкой Unicode
outStreamW.Type = 2;

outStreamW.Open();
outStreamW.WriteText(binString);

outStreamW.Position = 0;

var outStreamA = new ActiveXObject("ADODB.Stream"); // Текстовый поток с однобайтной кодировкой
outStreamA.Type = 2;
outStreamA.Charset = "windows-1251"; // Почему не ASCII? а потому что в случае ASCII будут исковерканы байты со кодами больше 127.

outStreamA.Open();

outStreamW.CopyTo(outStreamA); // Преобразование с одной кодировки в другую.

outStreamA.SaveToFile("c:\\writetest.exe", 2); // Сохранение потока в файл.

outStreamW.Close();
outStreamA.Close();


Протестировал я это дело таким образом:

// Читаем бинарный файл, специально для теста
var inStream = new ActiveXObject("ADODB.Stream");
inStream.Type = 1;

inStream.Open();
inStream.LoadFromFile("c:\\readtest.exe");

inStream.Position = 0;

var binData = inStream.Read();

inStream.Close();

///////////////////////////////////////////////////

// Преобразовываем бинарные данные в строку

var bufferSize = 100000; 
var rs = new ActiveXObject("ADODB.Recordset");

rs.Fields.Append("test", 201, bufferSize, 0x80);
rs.Open();

rs.AddNew();
rs.Fields("test").AppendChunk(binData);
rs.Update();

rs.MoveFirst();

var binString = rs("test").GetChunk(bufferSize);

rs.Close();

//////////////////////////////////////////////////

// Строка сейчас находится в Unicode, благодаря JavaScript
// Ну и далее уже записываем строку в файл с преобразованием в однобайтную кодировку

var outStreamW = new ActiveXObject("ADODB.Stream");
outStreamW.Type = 2;

outStreamW.Open();
outStreamW.WriteText(binString);

outStreamW.Position = 0;

var outStreamA = new ActiveXObject("ADODB.Stream");
outStreamA.Type = 2;
outStreamA.Charset = "windows-1251";

outStreamA.Open();

outStreamW.CopyTo(outStreamA);

outStreamA.SaveToFile("c:\\writetest.exe", 2);

outStreamW.Close();
outStreamA.Close();


Применением diff получаем, что файлы writetest и readtest совпадают до байта.

C Уважением, Andir!
<< using(Rsdn@Home 1.1.4 beta 2){/* Работаем */} >>
Re: Получилось- ADODB.Stream запись бинарника, JScript only!
От: EugeNet.Spb  
Дата: 10.06.04 14:38
Оценка:
Огромное спасибо Andir-у за хорошо работающие мозги =)

Наконец-то получилось записать бинарник (генерился самим скриптом) не в юникоде.
Пиндосы (американы) отдыхают — они все советуют эту функцию на VBS писать, типа на JS низзя...

В качестве примера генерю и сохраняю PNG и открываю проводник с файлом...

Обязательно используйте charset ISO-8859-1, Windows-125* и ascii тут не сработают.

Строки с комментарием // unnecessary — просто для демонстрации...

PS: Извините за английские комментарии, привычка у меня такая, все по пиндосски писать...
<SCRIPT LANGUAGE=jscript>
/*
======== RUSSIAN ===================================================
Скрипт для сохраннения бинарных данных из JScript и их генерации в нем же.
Задумка EugeNet, реализовать помог Andir (почти весь исходник).

======== ENGLISH ===================================================
This is done by EugeNet with great help of Andir (http://RSDN.ru).
For the foreign founders I'm gonna say-

It's the only JScript on a web, that allows to save binary data
(there's many for VBScript) generated by script itself.
( Viruses still uses VB, until this day =) ).

KEYWORDS: ADODB stream binary save file hex generate unicode
*/

var outStreamW = new ActiveXObject("ADODB.Stream"); // Text stream in Unicode    charset
var outStreamA = new ActiveXObject("ADODB.Stream"); // Text stream in ISO-8859-1 charset
var binStr = '';
var objShell = new ActiveXObject("Shell.Application"); // unnecessary

outStreamW.Type = 2;
outStreamW.Open();
                                 // couples of HEX values
outStreamW.WriteText( hex2text( '89504E470D0A1A0A0000000D4948445200000027000000420803000000E3443FEE0000000C504C5445F0EEEEF95353F59393' ) );
outStreamW.WriteText( hex2text( 'FF04047F58B0FF000000097048597300002E2300002E230178A53F760000014249444154789CED955902C42008434DB8FF9D' ) );
outStreamW.WriteText( hex2text( 'A7AD4BD9AC1C60FCAA363E10115AF38361251D404D27520242A40414290171EB0A409112F0F6AEE2E1C33A033BEA0C1CA413' ) );
outStreamW.WriteText( hex2text( '900374022ECE37900BF30D5494EBB380FB061AA7F6401AC41EE8CEB803D20176C007C76B1C8000D0930A5D4A208D35658D61' ) );
outStreamW.WriteText( hex2text( '9069D28A3821E6CC60FB5E1013A2B679AB7CB7749B026F1A7ADB74157362EE49B9417D1C1349172D636DAF83F1DE7EEB3889' ) );
outStreamW.WriteText( hex2text( 'F729E7B943EE7434B762CFA1269C81EBF74B1BC035E3B80215671DB267E14AABF523E6C57B46F3E315B6960BA16DC4B49E89' ) );
outStreamW.WriteText( hex2text( 'A4F3282F0BD4897F1A2C7606D43BC35F57D7857A1375CF0DF9C297E87A6AF9040B3A2E9DAF48C11134575A32DD0439A0D7AD' ) );
outStreamW.WriteText( hex2text( 'A70857846C00D4DF50349D4C55A45D5B31B2F104231269D95D2DA12F317D96ABBA0BDE5692B9A3EA847AF1794654544EBAE9' ) );
outStreamW.WriteText( hex2text( '5AC7F103F62B06FEC580AB3F0000000049454E44AE426082' ) );
outStreamW.Position = 0; //don't forget it or .Read will return 0 bytes

outStreamA.Type = 2;
outStreamA.Charset = 'ISO-8859-1'; // to avoid character conversion upper 127 ascii code
outStreamA.Open();
outStreamW.CopyTo( outStreamA ); // Copy unicoded stream to ISO-8859-1 stream
outStreamA.SaveToFile( 'c:\\YOUR FACE IN FBI DATABASE.png', 2 ); // save file as...

outStreamW.Close();
outStreamA.Close();

objShell.Open( 'C:\\' ); // unnecessary, opens Windows Explorer in root c:

// converts couples of HEX values to a string of chars
function hex2text( inHexStr ){
  binStr = ''; //using global variable will be faster, I think.
  for ( i = 0; i < ( inHexStr.length / 2 ); i++ ){
      binStr += String.fromCharCode( '0x' + inHexStr.substr( i * 2, 2 ) );
      }
      return binStr;
  }
</SCRIPT>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.