I am trying to save and load an xml file from my hard disk drive by calling the above code
TS.SaveToFile(Def_Response_XmlFile, TEncoding.UTF8);
XMLResponseDoc := LoadResponseDoc(Def_Response_XmlFile);
But when I called the following function
function LoadResponseDoc(const FileName: string): IXMLResponseDoc;
begin
ShowMessage('' +FileName);
ShowMessage('' +TXMLResponseDoc);
ShowMessage('' +TargetNamespace);
Result := LoadXMLDocument(FileName).GetDocBinding('ResponseDoc', TXMLResponseDoc, TargetNamespace) as IXMLResponseDoc;
ShowMessage('arrive here');
end;
I took as response the mentioned error.Any ideas what am I doing wrong?
Related
I am contemplating the migration from Advantage Native Delphi components to FireDAC. I have been searching for a way to determine how with FireDAC I can determine the method that was used to connect to the server - Remote, Local, AIS (Internet).
I would be looking for the equivalent of TAdsConnection.ConnectionType.
Thanks
Gary Conley
The function you're looking for is called AdsGetConnectionType. Its import you can find declared in the FireDAC.Phys.ADSCli module, but it's not used anywhere.
But it's not so difficult to get its address and call it by yourself. For example (not a good one):
uses
FireDAC.Stan.Consts, FireDAC.Phys.ADSCli, FireDAC.Phys.ADSWrapper;
var
FTAdsGetConnectionType: TAdsGetConnectionType = nil;
type
TADSLib = class(FireDAC.Phys.ADSWrapper.TADSLib)
end;
function GetConnectionType(Connection: TFDConnection): Word;
const
AdsGetConnectionTypeName = 'AdsGetConnectionType';
var
CliLib: TADSLib;
CliCon: TADSConnection;
Status: UNSIGNED32;
Output: UNSIGNED16;
begin
Result := 0;
CliCon := TADSConnection(Connection.CliObj);
CliLib := TADSLib(CliCon.Lib);
if not Assigned(FTAdsGetConnectionType) then
FTAdsGetConnectionType := CliLib.GetProc(AdsGetConnectionTypeName);
if Assigned(FTAdsGetConnectionType) then
begin
Status := FTAdsGetConnectionType(CliCon.Handle, #Output);
if Status = AE_SUCCESS then
Result := Word(Output)
else
FDException(CliLib.OwningObj, EADSNativeException.Create(Status, CliLib, nil),
{$IFDEF FireDAC_Monitor}True{$ELSE}False{$ENDIF});
end
else
FDException(CliLib.OwningObj, [S_FD_LPhys, CliLib.DriverID],
er_FD_AccCantGetLibraryEntry, [AdsGetConnectionTypeName]);
end;
Possible usage:
case GetConnectionType(FDConnection1) of
ADS_AIS_SERVER: ShowMessage('AIS server');
ADS_LOCAL_SERVER: ShowMessage('Local server');
ADS_REMOTE_SERVER: ShowMessage('Remove server');
end;
I'm trying to save a configtable(parsed to string) to a file wich is created just in time.
local cfg_string = table.tostring(cfg_table)
local file_name = ""
local cfg_file = ""
file_name = com:line(nil) -- reads a line of input from user via terminal
file_name = string.format("some_prefix-%s-some_suffix.lua",file_name)
-- file does NOT exist at this line
cfg_file = io.open("/dir/subdir/"..file_name,"w")
-- file now should exist
os.syslog(type(file_name)) -> string
os.syslog(type(cfg_file)) -> nil
os.syslog(type(cfg_string)) -> string
cfg_file:write(cfg_string)
cfg_file:write(cfg_string) throws "attempt to call "write" a nil value".
So hu,.. cfg_file is nil I know, but why? I also tried to io.open() with "a" flag, but this doesn't work too. The directory exists!
Thanks for your help.
Actually, my code is working. The error is thrown because missig write-permission to dir.
Everyone with such Errors should try
handle_name, err = io.open(file,"w")
print(err)
So my current task involves taking a given string of text (Ex: ABC123) and encrypting it using LockBox3's EncryptString(source, target) function. I can successfully encrypt the string and get the output to save to a .txt file.
The next step in this process is to then use LockBox3's EncryptFile(source, target) function to take the .txt containing my already-encrypted string and encrypting said file using AES-128 (same as the string encryption but with diff password)
Basically, I can get the string to encrypt correctly and output to a .txt file. I then request that the user grab the .txt, and bring it into my program. The program then attempts to take that file and encrypt it further. When I do this, I get a file to output.. however when I go to decrypt said file the resulting .txt does not contain the original text.. or any text for that matter. I am basically confused as to how I should be going about encrypting the .txt file. Any suggestions? I apologize if this question/code is not specific enough. Please let me know what else, if anything I need to make clear about the situation in order to better help you guys understand what I'm struggling with! Thanks!
EDIT1:
Alright everyone, thanks for the suggestions. To clarify:
The stream I have in the decryption process is to be used later, so that after I have decrypted the file, I can read from it and decrypt the remaining encrypted (from the first step) string.
To clarify further:
My codec (Codec1) for encrypting the string is using AES-128 with CBC, with a tag of "0" and an AsymetricKeySize of 1024 (which, Im pretty sure is irrelevant for this type of encryption correct?) My codec for encrypting FILES (Codec2 above) has the same settings, however the passwords for Codec1 and Codec2 are different. Basically, I am using Codec1 to encrypt a string and write it to a .txt, and then I am using Codec2 to encrypt said file.. eventually decrypt it and use the Stream to read from said file and decrypt that string using Codec1 again.
my file encryption/decryption code:
String Encryption:
procedure TForm1.Button1Click(Sender: TObject);
begin
codec1.Password := WORD_1;
//Begin encryption
sPlainText := Serial_number.Number; //Store Serial Number of machine
codec1.EncryptString(sPlainText,CipherText); //Encrypt (base64)
listbox2.Clear;
listbox2.AddItem(Ciphertext, AnsiCipher);
end;
Write encrypted string to a file and save it:
saveDialog := TSaveDialog.Create(self);
saveDialog.Title := 'Choose location to save Authentication Code';
saveDialog.InitialDir := 'C:\';
saveDialog.DefaultExt := '';
saveDialog.FilterIndex := 1;
saveDialog.Execute();
glb_fileName1 := saveDialog.FileName;
//open stream and write cipher to a .txt of chosen location
try
Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmOpenReadWrite);
except
Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmCreate);
end;
for k := 1 to (Length(CipherText)) do
buff[k] := byte(CipherText[k]);
ptr := #buff[1];
Stream.WriteBuffer(ptr^, Length(CipherText));
Stream.Free;
saveDialog.Free;
Grab location of .txt for file encryption:
procedure TForm1.Button4Click(Sender: TObject);
var
fileName : string;
holder_obj : TSerial_number;
begin
holder_obj := Tserial_number.Create;
listbox4.Clear;
if OpenTextFileDialog1.Execute() then
fileName := OpenTextFileDialog1.FileName;
listbox4.AddItem(filename, holder_obj);
end;
File Encryption:
Codec2.Password := WORD_2;
sCrypt := glb_fileName1 + '_enc.txt';
Codec2.EncryptFile(glb_fileName1+'.txt', sCrypt);
Grab Encrypted File for decryption:
procedure TForm1.Button3Click(Sender: TObject);
var
holder_obj : TSerial_number;
begin
holder_obj := Tserial_number.Create;
listbox3.Clear;
if OpenTextFileDialog1.Execute() then
glb_fileName2 := OpenTextFileDialog1.FileName;
listbox3.AddItem(glb_filename2, holder_obj);
end;
File Decryption (opening a stream to read from the decrypted file once I have it, so that I can decrypt the encrypted string it contains):
procedure TForm1.Button5Click(Sender: TObject);
var
saveDialog : TSaveDialog;
begin
saveDialog := TSaveDialog.Create(self);
saveDialog.Title := 'Choose location to save Decrypted Authentication Code';
saveDialog.InitialDir := 'C:\';
saveDialog.DefaultExt := '';
saveDialog.Execute();
glb_fileName1:= saveDialog.FileName;
//open stream and write cipher to a .txt of chosen location
try
Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmOpenReadWrite);
except
Stream := TFileStream.Create(saveDialog.GetNamePath + saveDialog.FileName + '.txt', fmCreate);
end;
Stream.Free;
Codec2.Password := WORD_2;
Codec2.DecryptFile(glb_fileName2, saveDialog.FileName + '.txt');
saveDialog.Free;
end;
The code you provided is way to complicated to try and see what is going wrong. If you are just trying to see if the encoding/decoding works you should only need simple code like the code below. Just put a test file on your drive and hardcode the names. That will let you know that the encoding/decoding works if the InputFile.txt and Un-EncryptedFile.text are the same.
Once you have the working then you can start to build up your full routines. The code you have posted is really confusing with the globals being used between the button clicks and just named 1, 2, etc. You have streams created that do nothing and only confuse the issue more. Strip things back to the basics and get that working first.
procedure TestEncodeDecode();
begin
Codec2.Password := WORD_2;
Codec2.EncryptFile('c:\InputFile.txt', 'c:\EncryptedFile.txt');
Codec2.DecryptFile('c:\EncryptedFile.txt', 'c:\Un-EncryptedFile.txt');
end;
I too am confused about what your question is asking. At the risk of misinterpreting your question, I have assumed that you are trying:
Encrypt a string;
Store the encrypted string in a file
Encrypt the file (double encryption)
Reverse the previous steps to reconstruct the original string.
The selftest() method proves that this works.
If this interpretation is correct, please consider something like the following solution. (Tested in Delphi 2010. Not test in XE2)
unit uDoubleEncrypt;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, uTPLb_CryptographicLibrary, uTPLb_BaseNonVisualComponent,
uTPLb_Codec;
type
TmfmDoubleEncrypt = class(TForm)
Codec1: TCodec;
Codec2: TCodec;
CryptographicLibrary1: TCryptographicLibrary;
btnGo: TButton;
memoLog: TMemo;
dlgSave1: TSaveDialog;
dlgOpen1: TOpenDialog;
procedure btnGoClick(Sender: TObject);
private
FFileName_Plain, FFileName_Cipher: string;
sSerial: string;
function EncryptStringWithCodec1( const sPlaintext: string): ansistring;
function GetFileName( dlgOpenX: TOpenDialog; var sFN: string): boolean;
procedure SaveAnsiStringToFile( const sFN: string; const sSerialCipherText: AnsiString);
function ReconstructSerial: string;
public
procedure Put( const LineFmt: string; const Args: array of const);
procedure Button1Click;
procedure Button4Click;
function SelfTest: boolean;
end;
var
mfmDoubleEncrypt: TmfmDoubleEncrypt;
implementation
{$R *.dfm}
procedure TmfmDoubleEncrypt.btnGoClick( Sender: TObject);
var
WORD_1, WORD_2: string;
begin
WORD_1 := 'red';
WORD_2 := 'blue';
sSerial := '123'; // Serial_number.Number; // Store Serial Number of machine
Codec1.Password := WORD_1;
Codec2.Password := WORD_2;
// Run the self test.
SelfTest;
// Clean up.
Codec1.Burn;
Codec2.Burn
// You may also want to delete temporary files here.
end;
function TmfmDoubleEncrypt.EncryptStringWithCodec1(
const sPlaintext: string): ansistring;
begin
// Assume Codec1 properties already set-up:
// 1. Password
// 2. CryptoLibrary
// 3. Cipher (at design-time)
// 4. Chain-mode
Codec1.Reset; // Normally not necessary. A defence agains the codec being left in a corrupt state.
Codec1.EncryptString( sPlaintext, result)
end;
function TmfmDoubleEncrypt.GetFileName(
dlgOpenX: TOpenDialog; var sFN: string): boolean;
begin
result := dlgOpenX.Execute;
if result then
sFN := dlgOpenX.FileName
end;
procedure TmfmDoubleEncrypt.Put(
const LineFmt: string; const Args: array of const);
begin
memoLog.Lines.Add( Format( LineFmt, Args))
end;
procedure TmfmDoubleEncrypt.SaveAnsiStringToFile(
const sFN: string; const sSerialCipherText: AnsiString);
const
Modes: array[boolean] of word = (fmCreate, fmOpenReadWrite);
var
SaveStream: TStream;
begin
SaveStream := TFileStream.Create( sFN, Modes[ FileExists( sFN)]);
try
SaveStream.Size := 0;
if sSerialCipherText <> '' then
SaveStream.WriteBuffer( sSerialCipherText[1], Length( sSerialCipherText))
finally
SaveStream.Free
end
end;
procedure TmfmDoubleEncrypt.Button1Click;
// This method is equivalent to gEdit101's Button1Click()
var
sPlainText: string;
sSerialCipherText: AnsiString;
sFN: string;
begin
sPlainText := sSerial;
sSerialCipherText := EncryptStringWithCodec1( sPlainText);
Put( 'Encrypted serial number is %s', [sSerialCipherText]);
if GetFileName( dlgOpen1, sFN) then
begin
SaveAnsiStringToFile( sFN, sSerialCipherText);
FFileName_Plain := sFN; // Store for Button4Click()
Put('encrypted serial number save to file "%s".',[sFN])
end;
end;
procedure TmfmDoubleEncrypt.Button4Click;
// This method is equivalent to gEdit101's Button4Click()
var
sPlainText: string;
sSerialCipherText: AnsiString;
sFN: string;
begin
Codec2.Reset;
FFileName_Cipher := FFileName_Plain + '_enc.dat'; // Not a text file. + '_enc.txt' would be wrong.
Codec2.EncryptFile( FFileName_Plain, FFileName_Cipher);
Put( 'Double Encrypted serial number is now stored in file "%s"', [FFileName_Cipher]);
end;
function TmfmDoubleEncrypt.ReconstructSerial: string;
var
CipherStream, PlainStream: TStream;
sEncryptedSerial: AnsiString;
begin
CipherStream := TFileStream.Create( FFileName_Cipher, fmOpenRead);
PlainStream := TMemoryStream.Create;
try
Codec2.Reset;
Codec2.DecryptStream( PlainStream, CipherStream);
PlainStream.Position := 0;
SetLength( sEncryptedSerial, PlainStream.Size);
if Length( sEncryptedSerial) > 0 then
PlainStream.ReadBuffer( sEncryptedSerial[1], Length( sEncryptedSerial));
Codec1.Reset;
Codec1.DecryptString( result, sEncryptedSerial)
finally
CipherStream.Free;
PlainStream.Free
end
end;
function TmfmDoubleEncrypt.SelfTest: boolean;
var
sRecon: string;
begin
Put('Commencing self test...',[]);
try
Button1Click; // 1st encryption
Button4Click; // 2nd encryption
sRecon := ReconstructSerial; // Reconstruction
result := sSerial = sRecon
finally
Put('Finished self test. Result = %s',[BoolToStr( result, True)]);
end;
end;
end.
The dfm for this unit is ...
object mfmDoubleEncrypt: TmfmDoubleEncrypt
Left = 0
Top = 0
Caption = 'Double Encrypt'
ClientHeight = 304
ClientWidth = 643
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
DesignSize = (
643
304)
PixelsPerInch = 96
TextHeight = 13
object btnGo: TButton
Left = 8
Top = 8
Width = 75
Height = 25
Caption = 'Go'
TabOrder = 0
OnClick = btnGoClick
end
object memoLog: TMemo
Left = 8
Top = 39
Width = 627
Height = 257
Anchors = [akLeft, akTop, akRight, akBottom]
Color = clInfoBk
ReadOnly = True
ScrollBars = ssVertical
TabOrder = 1
end
object Codec1: TCodec
AsymetricKeySizeInBits = 1024
AdvancedOptions2 = []
CryptoLibrary = CryptographicLibrary1
Left = 440
Top = 112
StreamCipherId = 'native.StreamToBlock'
BlockCipherId = 'native.AES-128'
ChainId = 'native.CBC'
end
object Codec2: TCodec
AsymetricKeySizeInBits = 1024
AdvancedOptions2 = []
CryptoLibrary = CryptographicLibrary1
Left = 536
Top = 112
StreamCipherId = 'native.StreamToBlock'
BlockCipherId = 'native.AES-128'
ChainId = 'native.CBC'
end
object CryptographicLibrary1: TCryptographicLibrary
Left = 480
Top = 48
end
object dlgSave1: TSaveDialog
InitialDir = 'C:\Temp'
Title = 'Choose location to save Authentication Code'
Left = 440
Top = 176
end
object dlgOpen1: TOpenDialog
InitialDir = 'C:\'
Left = 536
Top = 176
end
end
I am uploading a file via the following code.
After a successful upload I am attempting to Delete the file but I am getting a 32 - File in use error.
Can anyone tell me how I can resolve this file in use error? The following code is uploading the file, but not releasing it when done..
var
HTTP: TidHTTP;
SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
PostData: TIdMultiPartFormDataStream;
ResponseStream: TStringStream;
Delete : Boolean;
begin
ResponseStream := TStringStream.Create('');
HTTP := TidHTTP.Create(nil);
SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
SSLIOHandler.SSLOptions.Method := sslvSSLv3;
HTTP.ReadTimeout := 30000; //30 seconds
HTTP.ConnectTimeout := 30000; //30 seconds
HTTP.IOHandler := SSLIOHandler;
HTTP.HTTPOptions := [hoKeepOrigProtocol];
HTTP.ProtocolVersion := pv1_1;
PostData := TIdMultiPartFormDataStream.Create;
PostData.AddFormField('username', 'demo');
PostData.AddFormField('password', 'demo');
PostData.AddFormField('action', 'upload');
PostData.AddFormField('accountno', 'demo');
PostData.AddFile('uploadedfile', FileName, GetMIMETypeFromFile(FileName));
HTTP.Request.ContentType := PostData.RequestContentType;
HTTP.Post('http://uploadsite.com/ex/exampleAPI.asmx/Process', PostData, ResponseStream);
if AnsiContainsStr(ResponseStream.DataString, 'Done') then
Delete := True;
finally
SSLIOHandler.Free;
HTTP.Free;
ResponseStream.Free;
end;
if Delete then
if DeleteFile(BFlashFileName) then
ShowMessage('Deleted')
else ShowMessage(BFlashFileName+' not deleted, error = '+
IntToStr(GetLastError));
Call the Clear method of your TIdMultiPartFormDataStream instance before attempting to delete the file. If you don't need it anymore, freeing it will also amount to same (i.e. PostData.Free). Currently, it looks like you're leaking your PostData variable.
While TIdMultiPartFormDataStream is clearing its Fields collection, the file stream created by the AddFile method will be destroyed closing the file's handle.
I've been searching now for HOURS on Google (and here).
And I cannot find a solution.
I want to CHANGE the "Created Filetime" (= creation filetime) in DELPHI 6.
Not the "Modified file time" (for which a simple call to "FileSetDate()" is needed)
and not the "Last accessed file time".
How do I do this?
Call the SetFileTime Windows API function. Pass nil for lpLastAccessTime and lpLastWriteTime if you only want to modify the creation time.
You will need to obtain a file handle by calling CreateFile, or one of the Delphi wrappers, so this is not the most convenient API to use.
Make life easier for yourself by wrapping the API call up in a helper function that receives the file name and a TDateTime. This function should manage the low-level details of obtaining and closing a file handle, and converting the TDateTime to a FILETIME.
I would do it like this:
const
FILE_WRITE_ATTRIBUTES = $0100;
procedure SetFileCreationTime(const FileName: string; const DateTime: TDateTime);
var
Handle: THandle;
SystemTime: TSystemTime;
FileTime: TFileTime;
begin
Handle := CreateFile(PChar(FileName), FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if Handle=INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
DateTimeToSystemTime(DateTime, SystemTime);
if not SystemTimeToFileTime(SystemTime, FileTime) then
RaiseLastOSError;
if not SetFileTime(Handle, #FileTime, nil, nil) then
RaiseLastOSError;
finally
CloseHandle(Handle);
end;
end;
I had to add the declaration of FILE_WRITE_ATTRIBUTES because it is not present in the Delphi 6 Windows unit.
Based on FileSetDate, you can write a similar routine:
function FileSetCreatedDate(Handle: Integer; Age: Integer): Integer;
var
LocalFileTime, FileTime: TFileTime;
begin
Result := 0;
if DosDateTimeToFileTime(LongRec(Age).Hi, LongRec(Age).Lo, LocalFileTime) and
LocalFileTimeToFileTime(LocalFileTime, FileTime) and
SetFileTime(Handle, #FileTime, nil, nil) then Exit;
Result := GetLastError;
end;