mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
ADD: MacCloud/DropBox step-2: basic utils
This commit is contained in:
parent
7a974dde4c
commit
e5ba69a40e
1 changed files with 421 additions and 0 deletions
421
plugins/wfx/MacCloud/src/util/uminiutil.pas
Normal file
421
plugins/wfx/MacCloud/src/util/uminiutil.pas
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
{
|
||||
Notes:
|
||||
1. contains only the most basic util
|
||||
2. make full use of Cocoa native facilities:
|
||||
json serialization/deserialization
|
||||
hash
|
||||
string conversion
|
||||
file tools
|
||||
3. the purpose is to avoid dependencies on other libraries
|
||||
}
|
||||
|
||||
unit uMiniUtil;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$modeswitch objectivec2}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Generics.Collections,
|
||||
CocoaAll, uMiniCocoa;
|
||||
|
||||
type
|
||||
|
||||
TQueryItemsDictonary = specialize TDictionary<string, string>;
|
||||
|
||||
{ THttpUtil }
|
||||
|
||||
THttpUtil = class
|
||||
public
|
||||
class function toQueryItems( const lclItems: TQueryItemsDictonary ): NSArray;
|
||||
class procedure openInSafari( const urlPart: String; lclItems: TQueryItemsDictonary );
|
||||
class function queryValue( components: NSURLComponents; const name: String ): String;
|
||||
end;
|
||||
|
||||
{ THttpClientUtil }
|
||||
|
||||
THttpClientUtil = class
|
||||
public
|
||||
class function toQueryItems( const lclItems: TQueryItemsDictonary ): NSArray;
|
||||
class procedure openInSafari( const urlPart: String; lclItems: TQueryItemsDictonary );
|
||||
class function queryValue( components: NSURLComponents; const name: String ): String;
|
||||
end;
|
||||
|
||||
{ THashUtil }
|
||||
|
||||
THashUtil = class
|
||||
public
|
||||
class function sha256AndBase64( const input: String ): String;
|
||||
end;
|
||||
|
||||
{ TStringUtil }
|
||||
|
||||
TStringUtil = class
|
||||
public
|
||||
class function generateRandomString( const length: Integer ): String;
|
||||
class function widecharsToString(const S: pwidechar): String;
|
||||
class procedure stringToWidechars(const buffer: pwidechar; const S: String);
|
||||
end;
|
||||
|
||||
{ TJsonUtil }
|
||||
|
||||
TJsonUtil = class
|
||||
public
|
||||
class function dumps( const Elements: Array of Const; const ensureAscii: Boolean = False ): String;
|
||||
class function parse( const jsonString: String ): NSDictionary;
|
||||
class function getString( const json: NSDictionary; const key: String ): String;
|
||||
class function getBoolean( const json: NSDictionary; const key: String ): Boolean;
|
||||
class function getInteger( const json: NSDictionary; const key: String ): Integer;
|
||||
class function getArray( const json: NSDictionary; const key: String ): NSArray;
|
||||
end;
|
||||
|
||||
{ TFileUtil }
|
||||
|
||||
TFileUtil = class
|
||||
public
|
||||
class function exists( const path: String ): Boolean;
|
||||
class function filesize( const path: String ): Integer;
|
||||
end;
|
||||
|
||||
TLogProc = procedure ( const MsgType: Integer; const message: String );
|
||||
|
||||
{ TLogUtil }
|
||||
|
||||
TLogUtil = class
|
||||
private class var
|
||||
_logProc: TLogProc;
|
||||
_pluginNumber: Integer;
|
||||
public
|
||||
class procedure setLogProc( const logProc: TLogProc );
|
||||
class procedure log( const MsgType: Integer; const message: String );
|
||||
class procedure logInformation( const message: String );
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
CC_SHA256_DIGEST_LENGTH = 32;
|
||||
|
||||
function CC_SHA256(data: Pointer; len: LongWord; md: Pointer): Pointer; cdecl; external;
|
||||
|
||||
|
||||
{ THttpUtil }
|
||||
|
||||
class function THttpUtil.toQueryItems( const lclItems: TQueryItemsDictonary ): NSArray;
|
||||
var
|
||||
lclItem: TQueryItemsDictonary.TDictionaryPair;
|
||||
cocoaItem: NSURLQueryItem;
|
||||
cocoaItems: NSMutableArray;
|
||||
begin
|
||||
cocoaItems:= NSMutableArray.arrayWithCapacity( lclItems.Count );
|
||||
for lclItem in lclItems do begin
|
||||
cocoaItem:= NSURLQueryItem.queryItemWithName_value(
|
||||
StringToNSString(lclItem.Key),
|
||||
StringToNSString(lclItem.Value) );
|
||||
cocoaItems.addObject( cocoaItem );
|
||||
end;
|
||||
Result:= cocoaItems;
|
||||
end;
|
||||
|
||||
class procedure THttpUtil.openInSafari(
|
||||
const urlPart: String; lclItems: TQueryItemsDictonary );
|
||||
var
|
||||
urlComponents: NSURLComponents;
|
||||
begin
|
||||
urlComponents:= NSURLComponents.componentsWithString( StringToNSString(urlPart) );
|
||||
urlComponents.setQueryItems( toQueryItems(lclItems) );
|
||||
NSWorkspace.sharedWorkspace.openURLs_withAppBundleIdentifier_options_additionalEventParamDescriptor_launchIdentifiers(
|
||||
NSArray.arrayWithObject( urlComponents.url ),
|
||||
NSSTR('com.apple.Safari'),
|
||||
0,
|
||||
nil,
|
||||
nil );
|
||||
FreeAndNil( lclItems );
|
||||
end;
|
||||
|
||||
class function THttpUtil.queryValue(components: NSURLComponents;
|
||||
const name: String): String;
|
||||
var
|
||||
cocoaName: NSString;
|
||||
queryItem: NSURLQueryItem;
|
||||
begin
|
||||
cocoaName:= StringToNSString( name );
|
||||
for queryItem in components.queryItems do begin
|
||||
if queryItem.name.isEqualToString( cocoaName ) then begin
|
||||
Result:= queryItem.value.UTF8String;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
Result:= EmptyStr;
|
||||
end;
|
||||
|
||||
{ THashUtil }
|
||||
|
||||
class function THashUtil.sha256AndBase64(const input: String): String;
|
||||
var
|
||||
sha256Buf: array [1..CC_SHA256_DIGEST_LENGTH] of Byte;
|
||||
sha256Data: NSData;
|
||||
base64String: NSString;
|
||||
begin
|
||||
CC_SHA256( @input[1], input.Length, @sha256Buf );
|
||||
sha256Data:= NSData.dataWithBytes_length( @sha256Buf, CC_SHA256_DIGEST_LENGTH );
|
||||
base64String:= sha256Data.base64EncodedStringWithOptions( 0 );
|
||||
base64String:= base64String.stringByReplacingOccurrencesOfString_withString( NSSTR('/'), NSSTR('_') );
|
||||
base64String:= base64String.stringByReplacingOccurrencesOfString_withString( NSSTR('+'), NSSTR('-') );
|
||||
base64String:= base64String.stringByReplacingOccurrencesOfString_withString( NSSTR('='), NSString.string_ );
|
||||
Result:= base64String.UTF8String;
|
||||
end;
|
||||
|
||||
{ TStringUtil }
|
||||
|
||||
class function TStringUtil.generateRandomString(const length: Integer): String;
|
||||
const
|
||||
samples = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
var
|
||||
randomString: TAnsiStringBuilder;
|
||||
randomValue: Integer;
|
||||
i: Integer;
|
||||
begin
|
||||
randomString:= TAnsiStringBuilder.Create( length );
|
||||
for i:=0 to length-1 do begin
|
||||
randomValue:= random(samples.Length) + 1;
|
||||
randomString.Append( samples[randomValue] );
|
||||
end;
|
||||
Result:= randomString.ToString;
|
||||
randomString.Free;
|
||||
end;
|
||||
|
||||
class function TStringUtil.widecharsToString(const S: pwidechar): String;
|
||||
var
|
||||
str: NSString;
|
||||
begin
|
||||
str:= NSString.stringWithCharacters_length( @s[0], StrLen(s) );
|
||||
Result:= str.UTF8String;
|
||||
end;
|
||||
|
||||
class procedure TStringUtil.stringToWidechars(const buffer: pwidechar;
|
||||
const S: String);
|
||||
var
|
||||
str: NSString;
|
||||
begin
|
||||
str:= StringToNSString( S );
|
||||
str.getCharacters( unicharPtr(buffer) );
|
||||
end;
|
||||
|
||||
{ TJsonUtil }
|
||||
|
||||
class function TJsonUtil.dumps(
|
||||
const Elements: array of const;
|
||||
const ensureAscii: Boolean = False ): String;
|
||||
var
|
||||
i: integer;
|
||||
jsonData: NSData;
|
||||
jsonString: NSString;
|
||||
json: NSMutableDictionary;
|
||||
key: NSString;
|
||||
value: NSObject;
|
||||
error: NSError;
|
||||
|
||||
function varToNSObject( const Element : TVarRec ): id;
|
||||
begin
|
||||
Result:= nil;
|
||||
With Element do
|
||||
case VType of
|
||||
vtString : Result:= StringToNSString( VString^ );
|
||||
vtAnsiString : begin
|
||||
if VPChar = nil then
|
||||
Result:= NSString.string_
|
||||
else
|
||||
Result:= NSString.stringWithUTF8String( VPChar );
|
||||
end;
|
||||
vtBoolean : Result:= NSNumber.numberWithBool( VBoolean );
|
||||
vtInteger : Result:= NSNumber.numberWithLongLong( VInteger );
|
||||
vtInt64 : Result:= NSNumber.numberWithLongLong( VInt64^ );
|
||||
vtQWord : Result:= NSNumber.numberWithLongLong( VQWord^ );
|
||||
end;
|
||||
end;
|
||||
|
||||
function escapeUnicode( oldString: NSString ): NSString;
|
||||
var
|
||||
newString: NSMutableString;
|
||||
c: unichar;
|
||||
i: Integer;
|
||||
begin
|
||||
newString:= NSMutableString.new;
|
||||
for i:=0 to oldString.length-1 do begin
|
||||
c:= oldString.characterAtIndex( i );
|
||||
if c > $7F then
|
||||
newString.appendFormat( NSSTR('\u%04x'), c )
|
||||
else
|
||||
newString.appendFormat( NSSTR('%C'), c );
|
||||
end;
|
||||
Result:= newString;
|
||||
newString.autorelease;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:= EmptyStr;
|
||||
|
||||
if ((High(Elements)-Low(Elements)) mod 2)=0 then
|
||||
Exit;
|
||||
|
||||
json:= NSMutableDictionary.new;
|
||||
i:= Low(Elements);
|
||||
while i<= High(Elements) do begin
|
||||
key:= varToNSObject( Elements[i] );
|
||||
inc( i );
|
||||
value:= varToNSObject( Elements[i] );
|
||||
inc( i );
|
||||
json.setValue_forKey( value, key );
|
||||
end;
|
||||
|
||||
error:= nil;
|
||||
jsonData:= NSJSONSerialization.dataWithJSONObject_options_error( json, 1 shl 3, @error );
|
||||
if error <> nil then
|
||||
Result:= EmptyStr
|
||||
else begin
|
||||
jsonString:= NSString.alloc.initWithData_encoding( jsonData, NSUTF8StringEncoding );
|
||||
if ensureAscii then
|
||||
jsonString:= escapeUnicode( jsonString );
|
||||
Result:= jsonString.UTF8String;
|
||||
end;
|
||||
|
||||
json.release;
|
||||
end;
|
||||
|
||||
class function TJsonUtil.parse(const jsonString: String): NSDictionary;
|
||||
var
|
||||
jsonData: NSData;
|
||||
error: NSError;
|
||||
begin
|
||||
error:= nil;
|
||||
jsonData:= StringToNSString(jsonString).dataUsingEncoding( NSUTF8StringEncoding );
|
||||
Result:= NSJSONSerialization.JSONObjectWithData_options_error( jsonData, 0, @error );
|
||||
if error <> nil then
|
||||
Result:= nil;
|
||||
end;
|
||||
|
||||
class function TJsonUtil.getString(const json: NSDictionary; const key: String ): String;
|
||||
begin
|
||||
Result:= NSString( json.objectForKey( StringToNSString(key) ) ).UTF8String;
|
||||
end;
|
||||
|
||||
class function TJsonUtil.getBoolean(const json: NSDictionary; const key: String
|
||||
): Boolean;
|
||||
begin
|
||||
Result:= NSNumber( json.objectForKey( StringToNSString(key) ) ).boolValue;
|
||||
end;
|
||||
|
||||
class function TJsonUtil.getInteger(const json: NSDictionary; const key: String
|
||||
): Integer;
|
||||
begin
|
||||
Result:= NSNumber( json.objectForKey( StringToNSString(key) ) ).longLongValue;
|
||||
end;
|
||||
|
||||
class function TJsonUtil.getArray(const json: NSDictionary; const key: String
|
||||
): NSArray;
|
||||
begin
|
||||
Result:= NSArray( json.objectForKey( StringToNSString(key) ) );
|
||||
end;
|
||||
|
||||
procedure defaultLogProc( const MsgType: Integer; const message: String );
|
||||
begin
|
||||
Writeln( 'DefaultLogger: ', message );
|
||||
end;
|
||||
|
||||
{ TFileUtil }
|
||||
|
||||
class function TFileUtil.exists(const path: String): Boolean;
|
||||
var
|
||||
cocoaPath: NSString;
|
||||
begin
|
||||
cocoaPath:= StringToNSString( path );
|
||||
Result:= NSFileManager.defaultManager.fileExistsAtPath( cocoaPath );
|
||||
end;
|
||||
|
||||
class function TFileUtil.filesize(const path: String): Integer;
|
||||
var
|
||||
fileAttributes: NSDictionary;
|
||||
filesizeNumber: NSNumber;
|
||||
begin
|
||||
fileAttributes:= NSFileManager.defaultManager.attributesOfItemAtPath_error(
|
||||
StringToNSString(path),
|
||||
nil );
|
||||
filesizeNumber:= fileAttributes.objectForKey( NSFileSize );
|
||||
Result:= filesizeNumber.longLongValue;
|
||||
end;
|
||||
|
||||
{ TLogUtil }
|
||||
|
||||
class procedure TLogUtil.setLogProc( const logProc: TLogProc );
|
||||
begin
|
||||
_logProc:= logProc;
|
||||
end;
|
||||
|
||||
class procedure TLogUtil.log( const MsgType: Integer; const message: String );
|
||||
begin
|
||||
_logProc( MsgType, message );
|
||||
end;
|
||||
|
||||
class procedure TLogUtil.logInformation( const message: String );
|
||||
begin
|
||||
log( 3, message );
|
||||
end;
|
||||
|
||||
{ THttpClientUtil }
|
||||
|
||||
class function THttpClientUtil.toQueryItems(
|
||||
const lclItems: TQueryItemsDictonary ): NSArray;
|
||||
var
|
||||
lclItem: TQueryItemsDictonary.TDictionaryPair;
|
||||
cocoaItem: NSURLQueryItem;
|
||||
cocoaItems: NSMutableArray;
|
||||
begin
|
||||
cocoaItems:= NSMutableArray.arrayWithCapacity( lclItems.Count );
|
||||
for lclItem in lclItems do begin
|
||||
cocoaItem:= NSURLQueryItem.queryItemWithName_value(
|
||||
StringToNSString(lclItem.Key),
|
||||
StringToNSString(lclItem.Value) );
|
||||
cocoaItems.addObject( cocoaItem );
|
||||
end;
|
||||
Result:= cocoaItems;
|
||||
end;
|
||||
|
||||
class procedure THttpClientUtil.openInSafari(
|
||||
const urlPart: String; lclItems: TQueryItemsDictonary );
|
||||
var
|
||||
urlComponents: NSURLComponents;
|
||||
begin
|
||||
urlComponents:= NSURLComponents.componentsWithString( StringToNSString(urlPart) );
|
||||
urlComponents.setQueryItems( toQueryItems(lclItems) );
|
||||
NSWorkspace.sharedWorkspace.openURLs_withAppBundleIdentifier_options_additionalEventParamDescriptor_launchIdentifiers(
|
||||
NSArray.arrayWithObject( urlComponents.url ),
|
||||
NSSTR('com.apple.Safari'),
|
||||
0,
|
||||
nil,
|
||||
nil );
|
||||
FreeAndNil( lclItems );
|
||||
end;
|
||||
|
||||
class function THttpClientUtil.queryValue(components: NSURLComponents;
|
||||
const name: String): String;
|
||||
var
|
||||
cocoaName: NSString;
|
||||
queryItem: NSURLQueryItem;
|
||||
begin
|
||||
cocoaName:= StringToNSString( name );
|
||||
for queryItem in components.queryItems do begin
|
||||
if queryItem.name.isEqualToString( cocoaName ) then begin
|
||||
Result:= queryItem.value.UTF8String;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
Result:= EmptyStr;
|
||||
end;
|
||||
|
||||
initialization
|
||||
TLogUtil.setLogProc( @defaultLogProc );
|
||||
|
||||
end.
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue