mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-07-21 16:05:57 +02:00
408 lines
10 KiB
ObjectPascal
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.
|
|
|