You are not logged in.
Sorry if I insist but I have a problem with the generation of new tables by the framework in the sense that if I create a new database do not occur errors that occur instead if I upgrade an existing database.
The error is 405 and occurs when I run a simple code: AReport.Objects.ManyAdd(currentClient, AReport.id,Objects.id,True);
type
TSQLObject = class(TSQLFile)
private
...
end;
TSQLBaseReport = class(TSQLFile) //new table
private
...
end;
TSQLBaseReportObjects = class(TSQLRecordMany) //new table
private
fSource: TSQLBaseReport;
fDest: TSQLObject;
published
property Source: TSQLBaseReport read fSource;
property Dest: TSQLObject read fDest;
end;
TSQLReportObjects = class(TSQLBaseReportObjects); //new table
TSQLReport = class(TSQLBaseReport )
private
fObjects: TSQLBaseReportObjects;
public
...
published
property Objects: TSQLReportObjects read fObjects;
end;
//in the model I declare only the classes [TSQLReportObjects ,TSQLReport ,TSQLObject] and not [TSQLBaseReportObjects, TSQLBaseReport]
procedure Test_ManyAdd_Object_to_Report;
var
AReport :TSQLReport;
AObject: TSQLObject;
begin
AReport := TSQLReport.Create;
AReport.Created := Iso8601Now;
AReport.Modified := AReport.Created;
currentClient.Add(AReport, true);
AObject:= TSQLObject.Create;
AObject.Created := Iso8601Now;
AObject.Modified := AReport.Created;
currentClient.Add(AObject, true);
AReport.Objects.ManyAdd(currentClient, AReport.id,AObject.id,True); //Here the error occurs 405 with an old database created from the framework of months ago
end;thanks corchi
However, this only works if I cast TSQLXLSReport(ARec).Users.AddMany (ClientDB, AUser.ID, ARec.ID, true);
procedure TForm1.Button2Click(Sender: TObject);
var
ARec : TSQLXLSReport;
k:Integer;
begin
try
ARec := TSQLXLSReport.Create(ClientDB, 1);
if ARec.ID>0 then
begin
try
AUser:=TSQLUSer..Create;
AUser.Name := 'John 2'
ClientDB.Add(AUser,True);
AddUser(AUser,ARec);
finally
AUser.free;
end;
end;
finally
end;
end;
function AddUser(AUser:TSQLUSer;ARec : TSQLBaseReport;):Boolean;
begin
if not ARec.HasUser(ClientDB,AUser.Name)=0 then
ARec.Users.AddMany(ClientDB, AUser.ID, ARec.ID, true);
end;right???
I want to create a class TSQLBaseReport and then derive it into two class TSQLPDFReport and TSQLXLSReport , and to use that function "HasUser"declared only into TSQLBaseReport is correct or the framework does not support it. Show the following example
unit FileTables;
interface
{$I Synopse.inc}
type
TSQLFile = Class
...
end;
TSQLUser = class(TSQLFile)
...
end;
TSQLBaseReport = class(TSQLFile)
private
fUser: TSQLUserReports;
public
function HasUser(ClientDB: TSQLRestClientUri; const AUserName: RawUTF8;
const AUserID: Integer = -1): Boolean; overload;
// returned aRowID is an ID of row in PIVOT TABLE !!!
// so that we can access additional data stored in pivot connection
function HasUser(ClientDB: TSQLRestClientUri; const AUserName: RawUTF8;
const AUserID: Integer; var ARowID: Integer): Boolean; overload;virtual;Abstract;
published
property User: TSQLUserReports read fUser;
end;
TSQLUserBaseReports = class(TSQLRecordMany)
private
fSource: TSQLUser;
fDest: TSQLBaseReport;
published
property Source: TSQLUser read fSource;
property Dest: TSQLBaseReport read fDest;
end;
TSQLUserPDFReports = class(TSQLUserBaseReports)
private
fSource: TSQLUser;
fDest: TSQLPDFReport;
published
property Source: TSQLUser read fSource;
property Dest: TSQLPDFReport read fDest;
end;
TSQLUserXLSReports = class(TSQLUserBaseReports)
private
fSource: TSQLUser;
fDest: TSQLXLSReport;
published
property Source: TSQLUser read fSource;
property Dest: TSQLXLSReport read fDest;
end;
TSQLPDFReport = class(TSQLBaseReport)
private
fUsers: TSQLUserPDFReports;
published
property Users: TSQLUserPDFReports read fUsers;
end;
TSQLXLSReport = class(TSQLBaseReport)
private
fUsers: TSQLUserXLSReports;
published
property Users: TSQLUserXLSReports read fUsers;
end;
...
implementation
...
function TSQLBaseReport.HasUser(ClientDB: TSQLRestClientUri;
const AUserName: RawUTF8; const AUserID: Integer = -1): Boolean;
var
dummy: Integer;
begin
result := HasUser(ClientDB, AUserName, AUserID, dummy);
end;
function TSQLBaseReport.HasUser(ClientDB: TSQLRestClientUri;
const AUserName: RawUTF8; const AUserID: Integer;
var ARowID: Integer): Boolean;
var
User: TSQLUser;
begin
result := false;
ARowID := -1;
fUsers.FillMany(ClientDB, fID);
while fUsers.FillOne do
begin
if fUsers.Dest <> nil then
try
User := TSQLUser.Create(ClientDB, Integer(fUsers.Dest));
if ((AUserID = -1) and (User.Name = AUserName)) or
((AUserID > -1) and (User.ID = AUserID)) then
begin
result := True;
ARowID := fUsers.ID;
break;
end;
finally
FreeAndNil(User);
end;
end;
end;In the following example the user search is performed in the table TSQLPDFReport or in the table TSQLUserBaseReports.
NB: the TSQL*Base* tables are not created in the database, only derived tables are created
Uses FileTables;
....
procedure TForm1.Button1Click(Sender: TObject);
var
ARec : TSQLXLSReport;
k:Integer;
begin
try
ARec := TSQLXLSReport.Create(ClientDB, 1);
if ARec.ID>0 then
begin
if ARec.HasUser(ClientDB,'John')>0 then
Showmessage('the 1 report is assigned to John');
end;
finally
end;
end;No I do not use SQLiteAdmin.exe to insert new tables, but the framework, automatically creates the new tables and field from the classes and property that I specified in the model file.
So I added the classes that have generated new tables, but I realized that generated session only Administrator and not that of my user, ie if I open the database with SQLiteAdmin.exe see the tables only if I run it as Administrator otherwise I can not see and so does the framework seems to me
this is the exist table and I added only property "fFastReports: TSQLMailFastReports;" this is the existing table and I added only property "fFastReports: TSQLMailFastReports;" and the rispective classes of the new tables TSQLFastReport(TSQLReport) .
NB: TSQLReport already existed!
TSQLMail = class(TSQLFile)
private
fOwner: RawUTF8;
fSubject: RawUTF8;
fBody: RawUTF8;
fEnableMail: Boolean;
fReports: TSQLMailReports;
fFastReports: TSQLMailFastReports; //I insert this row in new version
fRecipients: TSQLMailRecipients;
fAttachment: RawUTF8;
fRecipient: RawUTF8;
// Mail
fMailAuthenticate: Boolean;
fMailUsername: RawUTF8;
fMailPassword: RawUTF8;
fMailSMTPPort: Integer;
fMailHost: RawUTF8;
fMailFrom: RawUTF8;
fMailTitle: RawUTF8;
public
constructor Create; override;
published
property Subject: RawUTF8 read fSubject write fSubject;
property Body: RawUTF8 read fBody write fBody;
property EnableMail: Boolean read fEnableMail write fEnableMail;
property Reports: TSQLMailReports read fReports;
property FastReports: TSQLMailFastReports read fFastReports; //I insert this row in new version
property Recipients: TSQLMailRecipients read fRecipients write fRecipients;
property Attachment: RawUTF8 read fAttachment write fAttachment;
property Recipient: RawUTF8 read fRecipient write fRecipient;
property MailAuthenticate: Boolean read fMailAuthenticate write fMailAuthenticate;
property MailUsername: RawUTF8 read fMailUsername write fMailUsername;
property MailPassword: RawUTF8 read fMailPassword write fMailPassword;
property MailSMTPPort: Integer read fMailSMTPPort write fMailSMTPPort;
property MailHost: RawUTF8 read fMailHost write fMailHost;
property MailFrom: RawUTF8 read fMailFrom write fMailFrom;
property MailTitle: RawUTF8 read fMailTitle write fMailTitle;
end;//I inserted the following lines into the new database model.
TSQLScheReport = class(TSQLReport)
private
fObjRecordClass: TypeRecordClass;
fRefID: Integer;
fPrinter: RawUTF8;
public
constructor Create; override;
published
property Printer: RawUTF8 read fPrinter write fPrinter;
property ObjRecordClass: TypeRecordClass read fObjRecordClass
write fObjRecordClass;
property RefID: Integer read fRefID write fRefID;
end;
TSQLMailFastReports = class(TSQLRecordMany)
private
fSource: TSQLMail;
fDest: TSQLScheReport;
published
property Source: TSQLMail read fSource;
property Dest: TSQLScheReport read fDest;
end;
I mean relation for the class "TSQLRecordMany"
I added 2 property (TSQLRecordMany) in an existing table with data
self.Relazione1.add (ADatabase, Self.ID, newID, true); does not work ,the error occurs 405
ok I understand
What about the problem of relations
If I add new fields and tables in the database does not save the relationship with the new tables, but if you destroy and create a new database works fine. Why?
Sorry but I can not understand how the writing of server SQLite.
I have a client/server application, the server writes in dir C: \ programdata \ DB \ SQLiteXXX.db.
If I run the My Server as Administrator and then I use SQLiteadmin.exe to read the database I do not see even a record. only if I run SQLiteadmin.exe as Administrator I can read the records entered by a client.
I'm doing something wrong, then I ask you this because if I run the server as an administrator but not as a normal user writes other records in the same table.
If I add new fields and tables in the database does not save the relationship with the new tables, but if you destroy and create a new database works fine. Why?
How do I modify a database of my clients if they lose their data every time I make a program copy from a old database to the new one?
Thanks Corchi
I have Win7 64bit and XE2
if SameText(ext,'.TXT') then begin
for i := 0 to Rep.Pages.Count-1 do
Content := Content+Rep.Pages[i]; // append content of every page
// export as ANSI text file, in the current code page
if not FileFromString(
{$ifdef UNICODE}
CurrentAnsiConvert.UnicodeBufferToAnsi(pointer(Content),length(Content))
{$else}
Content
{$endif} ,aName) then
exit;I corrected the code in this mode, but I dont know if it is correct
if SameText(ext,'.TXT') then begin
for i := 0 to Rep.PageCount-1 do
Content := Content+Rep.Pages[i].Text; // append content of every page
// export as ANSI text file, in the current code page
if not FileFromString(
{$ifdef UNICODE}
CurrentAnsiConvert.UnicodeBufferToAnsi(pointer(Content),length(Content))
{$else}
Content
{$endif} ,aName) then
exit;
end else
exit; // invalid extthanks
ok I'll try and will let you know
I'd like to reduce the visibility of the data as I go along with the selection of records. Below I have included an example that displays the filters that I were running automatically excluding records not interessati.
if the user User1 wants to see its jobs and its reports should not make a query master detail between jobs and reports to display only its reports but just type User1.Jobs.Reports.
It's possible to make this kind of behavior with your framework?
Table2
Jobs
id Name
1 job1
Reports
id Name
1 Rep1 (user1)
2 Rep2 (user1)
3 Rep1 (user2)
4 Rep1 (user3)
table of relationship between the job table and the table report
JobRepots
source Jobs
des Reports
Then there are the tables:
User
id Name
1 User1
2 User2
3 ....
table of relationship between the User table and the table report
UserRepots
source Users
des Reports
thanks corchi72
ok I have tested last version 2013-03-12 12:56:39 and it worked!!!
Thansk corchi
sorry but I could test the new version (2013-03-11 21:19:08) only just now, and this is the error occurs at compile time:
[DCC Error] mORMotToolBar.pas(1088): E2064 Left side cannot be assigned to
Thank corchi
I just tried to compile 64-bit XE2 but an error occurs at compile time:
[DCC Error] mORMoti18n.pas(1025): E2116 Invalid combination of opcode and operands
Can you give me a hint?
Thanks corchi
I created a client / server project with authentication, but do not know if the data filter is already active or do I develop it.
sorry, but I wanted to know if your framework can filter all the data in a database distinct for each user or user role.
I would like to reduce the visibility of data depending on the user or User role.
It's possible?
thanks corchi
"Did you use the latest 1.18 version from http://synopse.info/fossil/wiki?name=Get+the+source ?"
Yes, I use the last versione.
However, It may be helpful, this error that occurs:
First chance exception at $7566C41F. Exception class EInterfaceFactoryException with message
'Invalid fake IRemoteAction.Execute interface call: : {
"ErrorCode":500,
"ErrorText":"Exception EAccessViolation: Access violation at address 0064AFB9 in module 'PrjServer.exe'. Read of address 20202003"
}'.
Process ProjectClient.exe (296)
Tells you something?
I'm trying to use an OCX in the server.
If run the same code with the following statement works
type
TServiceRemoteAction = class(TInterfacedObject, IRemoteAction)
protected
fExecuteAction: TExecuteActions;
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
public // implements IRemoteAction methods
procedure Connect;
function Execute(AOwner: TComponent;aID:Integer;Force:Boolean): Boolean;
end;
.....
function TFileServer.ExecuteOCX(
var aParams: TSQLRestServerCallBackParams): Integer;
var
sID:RawUTF8;
RemoteAction :TServiceRemoteAction;
begin
UrlDecodeValue (aParams.Parameters,'ID=',sID,@aParams.Parameters);
try
RemoteAction := TServiceRemoteAction.Create;
RemoteAction.Connect;
RemoteAction.Execute(Strtoint(sID)); // my procedure that open Ocx create in a TDataModule
finally
RemoteAction.Free;
end;
result := 200; // success
end;This method, I added the source code. you see above
Why after 10 seconds this error occurs while the server is working?
First chance exception at $7566C41F. Exception class EInterfaceFactoryException with message 'Invalid fake IRemoteAction.Execute interface call: : '. Process Project.exe (6020)
infact I was looking at this blog
I had read something about this or I'm confusing?
Yesterday I asked you an example of how to connect the livebinding of Delphi XE3 with your framework, and since no one had posted I did some tests and I now place.
1) the first thing I had to edit mormot.pas and then as "Samples \ 04 - HTTP Client-Server \ Project04Client.dproj"
I created these two new methods because the existing ones were not compatible with the livebingi of delphi
unit mORMot;
...
uses
...
Generics.Collections;
...
procedure TSQLTableToObjectGenericList(aRecordClass: TSQLRecordClass;
aSourceTable: TSQLTable; aDestList: TObjectList<TSQLRecord>);
var R: TSQLRecord;
V: ^TSQLRecord;
Row: PPUtf8Char;
i: integer;
begin
R := aRecordClass.Create;
try
R.FillPrepare(aSourceTable);
aDestList.Count := aSourceTable.RowCount; // faster than manual Add()
V := @aDestList.List[0];
Row := @aSourceTable.fResults[aSourceTable.FieldCount]; // R^ points to first row of data
for i := 1 to aSourceTable.RowCount do begin
V^ := aRecordClass.Create; // TObjectList will free each instance
R.fFill.Fill(pointer(Row),V^);
Inc(Row,aSourceTable.FieldCount);
inc(V);
end;
finally
R.Free;
end;
end;
function TSQLRest.RetrieveGenericList(Table: TSQLRecordClass; FormatSQLWhere: PUTF8Char;
const BoundsSQLWhere: array of const; const aCustomFieldsCSV: RawUTF8=''): TObjectList<TSQLRecord>;
var SQL: RawUTF8;
T: TSQLTable;
begin
result := nil;
if (self=nil) or (Table=nil) then
exit;
SQL := FormatUTF8(FormatSQLWhere,[],BoundsSQLWhere);
if aCustomFieldsCSV<>'' then
T := InternalListJSON(Table,aCustomFieldsCSV,SQL) else
T := InternalListRecordsJSON(Table,SQL);
if T<>nil then
try
result := TObjectList<TSQLRecord>.Create;
TSQLTableToObjectGenericList(Table,T,result);
finally
T.Free;
end;
end;if you want to, I did it, I added the method constructor TSQLSampleRecord.Create(const AName, AQuestion: String);
type
/// here we declare the class containing the data
// - it just has to inherits from TSQLRecord, and the published
// properties will be used for the ORM (and all SQL creation)
// - the beginning of the class name must be 'TSQL' for proper table naming
// in client/server environnment
TSQLSampleRecord = class(TSQLRecord)
private
fQuestion: RawUTF8;
fName: RawUTF8;
fTime: TModTime;
public
constructor Create(const AName, AQuestion: String); overload;
published
property Time: TModTime read fTime write fTime;
property Name: RawUTF8 read fName write fName;
property Question: RawUTF8 read fQuestion write fQuestion;
end;
/// an easy way to create a database model for client and server
function CreateSampleModel: TSQLModel;
implementation
function CreateSampleModel: TSQLModel;
begin
result := TSQLModel.Create([TSQLSampleRecord]);
end;
constructor TSQLSampleRecord.Create(const AName, AQuestion: String);
begin
inherited Create;
FName := AName;
FQuestion := AQuestion;
end;then in form1 (Project04Client) I added a TStringGrid, a TAdapterBindSource and a TButton, then in the Livebinginds Designer I linked StringGrid1.* with AdapterBindSource1.*
...
private
MyPeople :TObjectList<TSQLRecord>;
....
procedure TForm1.Button1Click(Sender: TObject);
var
LSQLSampleRecord: TSQLSampleRecord;
begin
LSQLSampleRecord := TSQLSampleRecord.Create('John', 'Anders');
Database.Add(LSQLSampleRecord,true);
LSQLSampleRecord := TSQLSampleRecord.Create('toni', 'zzzz');
Database.Add(LSQLSampleRecord,true);
LSQLSampleRecord := TSQLSampleRecord.Create('bepi', 'xxxx');
Database.Add(LSQLSampleRecord,true);
MyPeople := TObjectList<TSQLRecord>.Create;
MyPeople := Database.RetrieveGenericList(TSQLSampleRecord,'',[]);
AdapterBindSource1.Adapter := TListBindSourceAdapter<TSQLSampleRecord>.Create(self, TObjectList<TSQLSampleRecord>(MyPeople), True);
AdapterBindSource1.Active := true;
end;ok now you can run the application and press the button1.
Sorry for my English, I hope to have helped you
corchi
Someone has developed an example with LiveBindings Delphi XE3 + mORMot?
ok, I just tested the fix and it works fine!!
thanks
The path to the *. Sqlite is correct, but I can not do any query, I left the server name white,and I filled in all the other fields, Admin, synopse.
I have noticed that I only sqliteadmin using the system table sqlite_sequence and I do not see sqlite_master, while if I use pro sqlite2009 see both the system tables.
What do you think?
I compiled with Delphi XE2 update 4
Synopse framework 1.18
SQLite3 engine 3.7.15.2
I can not see the list of tables in a Database generated with mMormot Framework.
Thanks corchi
very well, thanks
ok this is the code:
program Project04Server;
uses
Forms,
SynCrtSock,
SysUtils,
Unit2 in 'Unit2.pas' {Form1},
SampleData in '..\01 - In Memory ORM\SampleData.pas';
{$R *.res}
var delete: boolean;
begin
delete := (ParamCount=1) and SameText(ParamStr(1),'/DELETE');
// parameters below must match class function
// TTestClientServerAccess.RegisterAddUrl in mORMotHttpServer.pas:
THttpApiServer.AddUrlAuthorize('root','888',false,'+',delete);
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.Hi,
if I run the server service as a local user (not administrator) is there a technical reason for which a client does not connect to the server?
I am absolutely sure that there is no firewall running on the server itself.
Does it have to have specific permissions on the filesystem or on the Windows registry?
The reason for my request is because I cannot run the server as a local administrator due to security issues.
ok thanks
sorry for the delay in answering, but before I tried if it worked. and it works
..
// - use TSQLRest.Retrieve(Reference) to get a record value
AObject := TSQLObject(self.Retrieve(RecordReference(Model,Ctxt.Table,Ctxt.ID)));
Ctxt.Results([(AObject.filename]);
...thanks
I want to send as a parameter TSQLRecordClass, I know I can run on the server to retrive the correct table. (This function will be executed from multiple tables)
procedures in my server side is
procedure TFileServer.DataFromID(var Ctxt: TSQLRestServerCallBackParams);
var //aData: TSQLRawBlob;
sfilename:RawUTF8;
Id:Integer;
RecordClass: TSQLRecordClass;
AObject:TSQLObject;
begin
sfilename :='';
if not UrlDecodeNeedParameters(Ctxt.Parameters,'ID') then begin
Ctxt.Error('Missing Parameter');;
{$ifNdef SERVICE}
writeln('invalid Request');
{$ENDIF}
exit;
end;
while Ctxt.Parameters<>nil do begin
UrlDecodeInteger(Ctxt.Parameters,'ID=',Id,@Ctxt.Parameters);
UrlDecode(Ctxt.Parameters,'RECORDCLASS=',RecordClass,@Ctxt.Parameters);
end;
AObject := TSQLObject(RecordClass.Create);
if Self.Retrieve(id,AObject,false) then
begin
sfilename := AObject.filename;
Ctxt.Results([sfilename]);
end
else
begin
Ctxt.Error('invalid Request');
exit; // we need a valid record and its ID
end;
end;ok I will use flush sparingly, however AutoFlushTimeOut = 2 + with Appconsole readln; does not work, or rather writes only when they exceed the 4 kb and my Appconsole when part does not exceed 4 kb immediately because I septum in the following way
constructor TFileServer.Create(const ServerName,ServerPort: AnsiString;const aFilename: AnsiString);
var
inherited Create(CreateFileLicenseModel(true),aFilename,true);
self.CreateMissingTables(0);
Server := TSQLHttpServer.Create(ServerPort,[self]);
with QvLog.Family do begin
Level := [sllError,sllInfo,sllDebug,sllServiceCall]; //LOG_VERBOSE;//
AutoFlushTimeOut := 2;
DestinationPath := GetTempDir;
OnArchive := EventArchiveSynLZ;
//OnArchive := EventArchiveZip;
ArchiveAfterDays := 1; // archive after one day
// IncludeComputerNameInFileName:=true;
end;
QvLog.Add.Log(sllInfo,format('Database Name: %s',[ExpandFileName(aFilename)]));
QvLog.Add.Log(sllInfo,format('Server Port: %d',[strtoint(ServerPort)]));
QvLog.Add.Log(sllInfo,format('Server Name: %s',[ServerName]));
{$ifNdef SERVICE}
writeln('Server is Started');
{$ENDIF}
QvLog.Add.Log(sllInfo, 'Server is Started');
except
on E: Exception do
begin
QvLog.Add.Log(sllError,'Error launching the server' +#10+E.Message);
// handle initialization error here
end;
end;
QvLog.Family.SynLog.Flush(true);
end;and if I read the file.log want to find written:
20121212 16310611 info Server Port: 8001
20121212 16310611 info Server Name: localhost
20121212 16310611 info Server is Started
and not wait until the file reaches the size of 4kb, if I wait more than 2 seconds (as set above -> AutoFlushTimeOut := 2;) does not write anything
now I understand, I have to use TSQLlog.Family.SynLog.Flush (true) if I want the log to be written to the file before reaching the 4 kb, right?
ok thanks
you can read the log of the framework without having to read from the file? How can I display it in a Grid.
so that I can read the log from a client
thanks
well I found the problem, I am running an application with the directive {$ APPTYPE CONSOLE}
and with the command readln go out the application.
I saw that as long as the program is started, the log does not write anything to the file which will be written only after readln
sorry I read your example of the log but I was not yet clear to me, perhaps because it does not work! please you can write three lines of code that will allow me to create a log file. thanks
I noticed that the log is sometimes written only after I closed the console application. Why?
sorry but I do not understand why does not work the log, I mean the file is created but nothing is written. I do not understand why.
....create a server
self.CreateMissingTables(0);
Server := TSQLHttpServer.Create(ServerPort,[self]);//,ServerName);
self.OnUpdateEvent := OnDatabaseUpdateEvent;
with TSQLLog.Family do begin
Level := LOG_VERBOSE;
AutoFlushTimeOut := 2;
DestinationPath := GetTempDir;
OnArchive := EventArchiveSynLZ;
ArchiveAfterDays := 1; // archive after one day
end;
TSQLLog.Add.Log(sllInfo,'test corchi');I found a solution in my first code I sent the whole xml in the server parameter "@aData" and I could not read it because the parameter sendData no longer exists.
But now I saw that the entire xml sent is inserted into the
"sXML := Ctxt.Call.InBody". 'll explain with the code I correct:
Client side
if FHttpDatabase.URI(format('%s/%s',FHttpDatabase.Model.Root,StringtoUTF8('XMLAsData')])+UrlEncode(['filename',StringtoUTF8(sfilename)]),'PUT',@aResponse,nil,@aData).Lo=200 then
begin
....
end;Server side
procedure TFileServer.XMLAsData(var Ctxt: TSQLRestServerCallBackParams);
var //aData: TSQLRawBlob;
sfilename:RawUTF8;
XmlDoc: TNativeXml;
aData: RawUTF8 ;
Node: TXmlNode;
sXML:RawUTF8;
begin
//writeln('Start XMLAsData');
if not UrlDecodeNeedParameters(Ctxt.Parameters,'FILENAME') then begin
Ctxt.Error('Missing Parameter');;
{$ifNdef SERVICE}
writeln('invalid Request');
{$ENDIF}
exit;
end;
while Ctxt.Parameters<>nil do begin
UrlDecodeValue(Ctxt.Parameters,'FILENAME=',sfilename,@Ctxt.Parameters);
end;
{$ifNdef SERVICE}
writeln(format('filename: %s',[sfilename]));
{$ENDIF}
sXML := Ctxt.Call.InBody;
if length(sXML)>0 then
begin
{$ifNdef SERVICE}
if DebugHook<>0 then
writeln(format('Exist data: %s',[sXML]));
{$ENDIF}
try
XmlDoc := TNativeXml.Create(nil);
XmlDoc.ReadFromString(UTF8ToString(sXML));
XmlDoc.SaveToFile(sfilename);
{$ifNdef SERVICE}
writeln(format('Exist data: %s',[sfilename]));
{$ENDIF}
except
on E: Exception do
begin
{$ifNdef SERVICE}
writeln('Error launching the server' +#10+E.Message);
{$ENDIF}
Ctxt.Error('invalid Request');
exit; // we need a valid record and its ID
end;
end;
XmlDoc.Free;
end
else
begin
Ctxt.Error('invalid Request');
exit; // we need a valid record and its ID
end;
Ctxt.Results([sfilename]);
end;ok I changed the function in procedure, but the sencod parameter is too long, so it does not even run the code on the server
the new version does not work the following line of code, with which I was sending to the server a very large xml,
client side
if FHttpDatabase.URI(format('%s/%s',[FHttpDatabase.Model.Root,StringtoUTF8('XMLAsData')])+UrlEncode(['filename',StringtoUTF8(sfilename)]),'PUT',@aResponse,nil,@aData).Lo=200 thenServer side
no longer works
function TFileServer.XMLAsData(var aParams: TSQLRestServerCallBackParams): Integer;
var //aData: TSQLRawBlob;
sfilename:RawUTF8;
XmlDoc: TNativeXml;
aData: RawUTF8 ;
Node: TXmlNode;
begin
//writeln('Start XMLAsData');
if not UrlDecodeNeedParameters(aParams.Parameters,'FILENAME') then begin
result := 404; // invalid Request
{$ifNdef SERVICE}
writeln('invalid Request');
{$ENDIF}
exit;
end;
while aParams.Parameters<>nil do begin
UrlDecodeValue(aParams.Parameters,'FILENAME=',sfilename,@aParams.Parameters);
end;
{$ifNdef SERVICE}
writeln(format('filename: %s',[sfilename]));
{$ENDIF}
if length(aParams.SentData)>0 then
begin
{$ifNdef SERVICE}
if DebugHook<>0 then
writeln(format('Exist data: %s',[aParams.SentData]));
{$ENDIF}
try
XmlDoc := TNativeXml.Create(nil);
XmlDoc.ReadFromString(UTF8ToString(aParams.SentData));
XmlDoc.SaveToFile(sfilename);
{$ifNdef SERVICE}
writeln(format('Exist data: %s',[sfilename]));
{$ENDIF}
except
on E: Exception do
begin
{$ifNdef SERVICE}
writeln('Error launching the server' +#10+E.Message);
{$ENDIF}
result := 404; // invalid Request
exit; // we need a valid record and its ID
end;
end;
XmlDoc.Free;
end
else
begin
result := 404; // invalid Request
exit; // we need a valid record and its ID
end;
aParams.Resp := JSONEncodeResult([sfilename]);
//aResp := JSONEncodeResult([SynCommons.BinToHex(aData)]);
// idem: aResp := JSONEncode(['result',BinToHex(aRecord.fData)],TempMemoryStream);
result := 200; // success
end;I tried to use the following call but does not work,
now what can I use to send xml filename to the server?
client side
aResponse := FHttpDatabase.CallBackGetResult('XMLAsData',['filename',StringtoUTF8(sfilename),'XML',aData]);Server
function TFileServer.XMLAsData(var aParams: TSQLRestServerCallBackParams): Integer;
var //aData: TSQLRawBlob;
sfilename:RawUTF8;
XmlDoc: TNativeXml;
aData: RawUTF8 ;
Node: TXmlNode;
sXML:RawUTF8;
begin
//writeln('Start XMLAsData');
if not UrlDecodeNeedParameters(aParams.Parameters,'FILENAME') then begin
result := 404; // invalid Request
{$ifNdef SERVICE}
writeln('invalid Request');
{$ENDIF}
exit;
end;
if not UrlDecodeNeedParameters(aParams.Parameters,'XML') then begin
result := 404; // invalid Request
{$ifNdef SERVICE}
writeln('invalid Request');
{$ENDIF}
exit;
end;
while aParams.Parameters<>nil do begin
UrlDecodeValue(aParams.Parameters,'FILENAME=',sfilename,@aParams.Parameters);
UrlDecodeValue(aParams.Parameters,'XML=',sXML,@aParams.Parameters);
end;
{$ifNdef SERVICE}
writeln(format('filename: %s',[sfilename]));
{$ENDIF}
if length(sXML)>0 then
begin
{$ifNdef SERVICE}
if DebugHook<>0 then
writeln(format('Exist data: %s',[sXML]));
{$ENDIF}
try
XmlDoc := TNativeXml.Create(nil);
XmlDoc.ReadFromString(UTF8ToString(sXML));
XmlDoc.SaveToFile(sfilename);
{$ifNdef SERVICE}
writeln(format('Exist data: %s',[sfilename]));
{$ENDIF}
except
on E: Exception do
begin
{$ifNdef SERVICE}
writeln('Error launching the server' +#10+E.Message);
{$ENDIF}
result := 404; // invalid Request
exit; // we need a valid record and its ID
end;
end;
XmlDoc.Free;
end
else
begin
result := 404; // invalid Request
exit; // we need a valid record and its ID
end;
aParams.Results([sfilename]);
//aResp := JSONEncodeResult([SynCommons.BinToHex(aData)]);
// idem: aResp := JSONEncode(['result',BinToHex(aRecord.fData)],TempMemoryStream);
result := 200; // success
end;in the downloaded version if you compile the example Synfile an error occurs in the line
/// the type of custom main User Interface description of SynFile
TFileRibbonTabParameters = object(TSQLRibbonTabParameters)
/// the SynFile actions
Actions: TFileActions;
end;so I looked at the code below and saw that the old version
TSQLRibbonTabParameters = object
publicand not
{$ifndef UNICODE}
TSQLRibbonTabParameters = object
{$else}
TSQLRibbonTabParameters = record
{$endif}
publicmaybe you wanted to write {$ifdef UNICODE} TSQLRibbonTabParameters = object {$else}
ok now it works perfectly well! you're great
thanks corchi
my PasswordHashHexa was not blank, because I realized that the table AuthUser not accept blank password. Anyway, now I did some testing and I can create users with passwords blank. But my problem is that I use the same users to access ActiveDirectory is that normally SETUSER, so in this last case, I enter my username and password (Domain \ corchi and Password properly = '123 '). so if I Login with SETUSER ('Domain \ corchi', 123 ') works if I try login to ActiveDirectory with SETUSER ('','') not works because the field in the table AuthUser PasswordHashHexa contains '123' (value not encrypted)
thank corchi72
sorry but the error occurs, is successful OnsetUSer and then to the first statement that calls the db unleashes the event OnAuthentificationFailed!
sorry if I ask but you are working to fix the bug or not, I ask you this because otherwise I will use another road
thanks
This is my log as you can see there is no error in authentication:
C:\Users\corchi\Documents\Sviluppo\QV.exe 1.0.1.0 (2012-11-22 09:41:42)
Host=PCCORCHI User=corchi CPU=4*9-6-14857 OS=13.1=6.1.7601 Wow64=1 Freq=14318180
TSQLLog 1.17 2012-11-22T09:41:48
20121122 09414810 info Database Name: C:\ProgramData\QVDB\DB.Sqlite
20121122 09414810 info Server Port: 888
20121122 09414810 info Server Name: localhost
20121122 09414840 info TSQLite3HttpServer(034958C0) THttpApiServer(035224B8) initialized
20121122 09414842 info Server is Started
20121122 09424431 auth TFileServer(02CE6100) Windows Authentication success for DOMAIN\corchi
20121122 09424431 auth TAuthSession(02CF84C0) New User session DOMAIN\corchi/76 created
I do not understand at what point give error, because for me the routine Auth() works. but I wonder if I am the only one with this error because it seems very obvious if you run SETUSER (blank, blank) does not work!
thank corchi