lazarus/components/googleapis/demo/drive/frmmain.pp

408 lines
10 KiB
ObjectPascal

unit frmmain;
{$mode objfpc}{$H+}
// Define USESYNAPSE if you want to force use of synapse
{ $DEFINE USESYNAPSE}
// For version 2.6.4, synapse is the only option.
{$IFDEF VER2_6}
{$DEFINE USESYNAPSE}
{$ENDIF}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ComCtrls, synautil, IniFiles, googlebase, googleservice, googleclient,
googledrive;
Const
ILeaf = 0;
ILeafEmpty = 1;
type
{ TMainForm }
TAccessTokenState = (acsWaiting,acsOK,acsCancel);
TMainForm = class(TForm)
BCancel: TButton;
BSetAccess: TButton;
BRefreshFolders: TButton;
BRefreshFiles: TButton;
EAccessCode: TEdit;
GBAccess: TGroupBox;
Label1: TLabel;
LVFiles: TListView;
LTasks: TLabel;
LEAccess: TLabel;
SDDownload: TSaveDialog;
TVFolders: TTreeView;
procedure BCancelClick(Sender: TObject);
procedure BRefreshFilesClick(Sender: TObject);
procedure BSetAccessClick(Sender: TObject);
procedure BRefreshFoldersClick(Sender: TObject);
Procedure DoUserConsent(Const AURL : String; Out AAuthCode : String) ;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LVFilesDblClick(Sender: TObject);
procedure TVFoldersSelectionChanged(Sender: TObject);
private
{ private declarations }
FAccessState : TAccessTokenState;
FClient : TGoogleClient;
FDriveAPI: TDriveAPI;
procedure AddFolders(AParent: TTreeNode; AFolderID: String);
procedure ClearFileListView;
procedure ClearTreeView;
procedure LoadAuthConfig;
procedure SaveRefreshToken;
procedure ShowFolder(AFolderID: String);
public
{ public declarations }
end;
var
MainForm: TMainForm;
implementation
uses {$ifdef windows}windows,{$endif}
ssl_openssl,
jsonparser, // needed
fpjson,
fpoauth2,
lclintf,
fpwebclient,
frmselectdownload,
{$IFDEF USESYNAPSE}
ssl_openssl,
synapsewebclient
{$ELSE}
fphttpwebclient
{$ENDIF}
;
{$R *.lfm}
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
// Register Tasks resources.
TDriveAPI.RegisterAPIResources;
// Set up google client.
FClient:=TGoogleClient.Create(Self);
{$IFDEF USESYNAPSE}
FClient.WebClient:=TSynapseWebClient.Create(Self);
{$ELSE}
FClient.WebClient:=TFPHTTPWebClient.Create(Self);
{$ENDIF}
FClient.WebClient.RequestSigner:=FClient.AuthHandler;
FClient.WebClient.LogFile:='requests.log';
FClient.AuthHandler.WebClient:=FClient.WebClient;
FClient.AuthHandler.Config.AccessType:=atOffLine;
// We want to enter a code.
FClient.OnUserConsent:=@DoUserConsent;
// Create a Tasks API and connect it to the client.
FDriveAPI:=TDriveAPI.Create(Self);
FDriveAPI.GoogleClient:=FClient;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
end;
procedure TMainForm.LVFilesDblClick(Sender: TObject);
Var
Entry : TFile;
Request : TWebClientRequest;
Response: TWebClientResponse;
S,URL,LFN: String;
D : TJSONEnum;
begin
If Not (Assigned(LVFiles.Selected) and Assigned(LVFiles.Selected.Data)) then
Exit;
Entry:=TFile(LVFiles.Selected.Data);
if (Entry.DownloadUrl='')
and ((Entry.exportLinks=Nil) or (Entry.exportLinks.additionalProperties=Nil) or ((Entry.exportLinks.additionalProperties.Count)=0)) then
Exit;
if Entry.DownloadUrl<>'' then
URL:=TDriveAPI.APIBaseURL+'files/'+Entry.ID+'?alt=media'
else
begin
With TSelectDownloadForm.Create(Self) do
try
Formats.BeginUpdate;
For D in Entry.exportLinks.additionalProperties do
Formats.Add(D.Key);
if (ShowModal=mrOK) then
S:=Selected;
finally
Free;
end;
URL:=Entry.exportLinks.additionalProperties.Strings[S];
end;
SDDownload.FileName:=Application.Location+Entry.Title+'.'+Entry.fileExtension;
If Not SDDownload.Execute then
Exit;
Response:=Nil;
Request:=FClient.WebClient.CreateRequest;
try
Response:=FClient.WebClient.ExecuteSignedRequest('GET',URL,Request);
With TFileStream.Create(SDDownLoad.FileName,fmCreate) do
try
CopyFrom(Response.Content,0);
finally
Free;
end;
finally
Response.Free;
Request.Free;
end;
end;
procedure TMainForm.TVFoldersSelectionChanged(Sender: TObject);
begin
BRefreshFilesClick(Sender)
end;
procedure TMainForm.LoadAuthConfig;
Var
ini:TIniFile;
begin
ini:=TIniFile.Create('google.ini');
try
// Registered application needs tasks scope
FClient.AuthHandler.Config.ClientID:=ini.ReadString('Credentials','ClientID','');;
FClient.AuthHandler.Config.ClientSecret:=ini.ReadString('Credentials','ClientSecret','');
FClient.AuthHandler.Config.AuthScope:=ini.ReadString('Credentials','Scope','https://www.googleapis.com/auth/drive');
// We are offline.
FClient.AuthHandler.Config.RedirectUri:='urn:ietf:wg:oauth:2.0:oob';
// Session data
FClient.AuthHandler.Session.RefreshToken:=ini.ReadString('Session','RefreshToken','');
FClient.AuthHandler.Session.AccessToken:=ini.ReadString('Session','AccesToken','');
FClient.AuthHandler.Session.AuthTokenType:=ini.ReadString('Session','TokenType','');
FClient.AuthHandler.Session.AuthExpires:=ini.ReadDateTime('Session','AuthExpires',0);
FClient.AuthHandler.Session.AuthExpiryPeriod:=Ini.ReadInteger('Session','AuthPeriod',0);
finally
Ini.Free;
end;
end;
procedure TMainForm.SaveRefreshToken;
Var
ini:TIniFile;
begin
// We save the refresh token for later use.
if FClient.AuthHandler.Session.RefreshToken<>'' then
begin
ini:=TIniFile.Create('google.ini');
try
ini.WriteString('Session','RefreshToken',FClient.AuthHandler.Session.RefreshToken);
ini.WriteString('Session','AccessToken',FClient.AuthHandler.Session.AccessToken);
ini.WriteString('Session','TokenType',FClient.AuthHandler.Session.AuthTokenType);
ini.WriteDateTime('Session','AuthExpires',FClient.AuthHandler.Session.AuthExpires);
ini.WriteInteger('Session','AuthPeriod',FClient.AuthHandler.Session.AuthExpiryPeriod);
finally
Ini.Free;
end;
end;
end;
procedure TMainForm.ClearTreeView;
Var
I : Integer;
begin
With TVFolders.Items do
begin
BeginUpdate;
try
For I:=0 to Count-1 do
TObject(Item[i].Data).Free;
Clear;
finally
EndUpdate;
end;
end;
end;
procedure TMainForm.AddFolders(AParent : TTreeNode; AFolderID : String);
var
Entry: TFile;
Resource : TFilesResource;
EN : String;
Q : TFilesListOptions;
List : TFileList;
i : integer;
N : TTreeNode;
begin
Resource:=Nil;
try
Resource:=FDriveAPI.CreateFilesResource(Self);
// Search for folders of indicated folder only.
Q.q:='mimeType = ''application/vnd.google-apps.folder'' and '''+AFolderId+''' in parents';
Q.corpus:='';
q.maxResults:=0;
Q.pageToken:='';
Q.projection:='';
List:=Resource.list(Q);
SaveRefreshToken;
With TVFolders.Items do
begin
BeginUpdate;
try
if Assigned(List) then
for i:= 0 to Length(List.items)-1 do
begin
Entry:=List.items[i];
List.Items[i]:=Nil;
N:=AddChild(AParent,Entry.title);
N.Data:=Entry;
end;
finally
EndUpdate;
end;
end;
Application.ProcessMessages;
if Assigned(AParent) then
for I:=AParent.Count-1 downto 0 do
AddFolders(AParent.Items[i],TFile(AParent.Items[i].Data).id)
else if (TVFolders.Items.Count>0) then
for I:=TVFolders.Items.Count-1 downto 0 do
AddFolders(TVFolders.Items[i],TFile(TVFolders.Items[i].Data).id)
finally
FreeAndNil(Resource);
end;
end;
procedure TMainForm.BRefreshFoldersClick(Sender: TObject);
begin
LoadAuthConfig;
ClearTreeView;
AddFolders(Nil,'root');
end;
procedure TMainForm.BSetAccessClick(Sender: TObject);
begin
FAccessState:=acsOK;
GBAccess.Visible:=False;
end;
procedure TMainForm.BCancelClick(Sender: TObject);
begin
FAccessState:=acsCancel;
GBAccess.Visible:=False;
end;
procedure TMainForm.ClearFileListView;
Var
I : Integer;
begin
With LVFiles.Items do
begin
BeginUpdate;
try
For I:=0 to Count-1 do
TObject(Item[i].Data).Free;
Clear;
finally
EndUpdate;
end;
end;
end;
procedure TMainForm.BRefreshFilesClick(Sender: TObject);
begin
if (TVFolders.Selected=Nil) or (TVFolders.Selected.Data=Nil) then
ShowFolder('root')
else
ShowFolder(TFile(TVFolders.Selected.Data).ID);
end;
procedure TMainForm.ShowFolder(AFolderID : String);
var
Entry: TFile;
EN : String;
i:integer;
Q : TFilesListOptions;
List : TFileList;
Resource : TFilesResource;
LI : TListItem;
begin
ClearFileListView;
Resource:=Nil;
try
Resource:=FDriveAPI.CreateFilesResource(Self);
// Search for files of indicated folder only.
Q.q:='mimeType != ''application/vnd.google-apps.folder'' and '''+AFolderId+''' in parents';
List:=Resource.list(Q);
SaveRefreshToken;
With LVFiles.Items do
begin
BeginUpdate;
try
Clear;
if Assigned(List) then
for i:= 0 to Length(List.items)-1 do
begin
Entry:=List.items[i];
List.Items[i]:=Nil;
LI:=Add;
LI.Caption:=Entry.Title;
With LI.SubItems do
begin
Add(DateTimeToStr(Entry.createdDate));
Add(Entry.Description);
Add(BoolToStr(Entry.Editable,'Yes','No'));
Add(Entry.fileSize);
Add(Entry.lastModifyingUserName);
Add(Entry.downloadUrl);
Add(Entry.version);
Add(Entry.mimeType);
end;
Li.Data:=Entry;
end;
finally
EndUpdate;
end;
end;
Finally
Resource.Free;
end;
end;
Procedure TMainForm.DoUserConsent(Const AURL: String; Out AAuthCode: String);
begin
GBAccess.Visible:=True;
EAccessCode.Text:='<enter code here>';
FAccessState:=acsWaiting;
OpenUrl(AURL);
While (FAccessState=acsWaiting) do
Application.ProcessMessages;
if FAccessState=acsOK then
AAuthCode:=EAccessCode.Text;
GBAccess.Visible:=False;
end;
end.