mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
UPD: Use our own quoting of parameters from libmime.
This commit is contained in:
parent
517d889057
commit
fd280e0afe
5 changed files with 121 additions and 159 deletions
Binary file not shown.
|
|
@ -67,144 +67,3 @@ VFSAppDesktop mime_get_desktop_entry( const char* file_name )
|
|||
|
||||
return app;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse Exec command line of app desktop file, and translate
|
||||
* it into a real command which can be passed to g_spawn_command_line_async().
|
||||
* file_list is a null-terminated file list containing full
|
||||
* paths of the files passed to app.
|
||||
* returned char* should be freed when no longer needed.
|
||||
*/
|
||||
char* translate_app_exec_to_command_line( const VFSAppDesktop* app,
|
||||
GList* file_list )
|
||||
{
|
||||
char* file;
|
||||
GList* l;
|
||||
gchar *tmp;
|
||||
const char * pexec;
|
||||
GString* cmd = g_string_new("");
|
||||
gboolean add_files = FALSE;
|
||||
|
||||
for( pexec = app->exec; *pexec; ++pexec )
|
||||
{
|
||||
if( *pexec == '%' )
|
||||
{
|
||||
++pexec;
|
||||
switch( *pexec )
|
||||
{
|
||||
case 'U':
|
||||
for( l = file_list; l; l = l->next )
|
||||
{
|
||||
tmp = g_filename_to_uri( (char*)l->data, NULL, NULL );
|
||||
file = g_shell_quote( tmp );
|
||||
g_free( tmp );
|
||||
g_string_append( cmd, file );
|
||||
g_string_append_c( cmd, ' ' );
|
||||
g_free( file );
|
||||
}
|
||||
add_files = TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
if( file_list && file_list->data )
|
||||
{
|
||||
file = (char*)file_list->data;
|
||||
tmp = g_filename_to_uri( file, NULL, NULL );
|
||||
file = g_shell_quote( tmp );
|
||||
g_free( tmp );
|
||||
g_string_append( cmd, file );
|
||||
g_free( file );
|
||||
add_files = TRUE;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
case 'N':
|
||||
for( l = file_list; l; l = l->next )
|
||||
{
|
||||
file = (char*)l->data;
|
||||
tmp = g_shell_quote( file );
|
||||
g_string_append( cmd, tmp );
|
||||
g_string_append_c( cmd, ' ' );
|
||||
g_free( tmp );
|
||||
}
|
||||
add_files = TRUE;
|
||||
break;
|
||||
case 'f':
|
||||
case 'n':
|
||||
if( file_list && file_list->data )
|
||||
{
|
||||
file = (char*)file_list->data;
|
||||
tmp = g_shell_quote( file );
|
||||
g_string_append( cmd, tmp );
|
||||
g_free( tmp );
|
||||
add_files = TRUE;
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
for( l = file_list; l; l = l->next )
|
||||
{
|
||||
tmp = g_path_get_dirname( (char*)l->data );
|
||||
file = g_shell_quote( tmp );
|
||||
g_free( tmp );
|
||||
g_string_append( cmd, file );
|
||||
g_string_append_c( cmd, ' ' );
|
||||
g_free( file );
|
||||
}
|
||||
add_files = TRUE;
|
||||
break;
|
||||
case 'd':
|
||||
if( file_list && file_list->data )
|
||||
{
|
||||
tmp = g_path_get_dirname( (char*)file_list->data );
|
||||
file = g_shell_quote( tmp );
|
||||
g_free( tmp );
|
||||
g_string_append( cmd, file );
|
||||
g_free( tmp );
|
||||
add_files = TRUE;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
g_string_append( cmd, app->disp_name );
|
||||
break;
|
||||
case 'i':
|
||||
/* Add icon name */
|
||||
if( app->icon_name )
|
||||
{
|
||||
g_string_append( cmd, "--icon " );
|
||||
g_string_append( cmd, app->icon_name );
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
/* Location of the desktop file */
|
||||
break;
|
||||
case 'v':
|
||||
/* Device name */
|
||||
break;
|
||||
case '%':
|
||||
g_string_append_c ( cmd, '%' );
|
||||
break;
|
||||
case '\0':
|
||||
goto _finish;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* not % escaped part */
|
||||
{
|
||||
g_string_append_c ( cmd, *pexec );
|
||||
}
|
||||
}
|
||||
_finish:
|
||||
if( ! add_files )
|
||||
{
|
||||
g_string_append_c ( cmd, ' ' );
|
||||
for( l = file_list; l; l = l->next )
|
||||
{
|
||||
file = (char*)l->data;
|
||||
tmp = g_shell_quote( file );
|
||||
g_string_append( cmd, tmp );
|
||||
g_string_append_c( cmd, ' ' );
|
||||
g_free( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
return g_string_free( cmd, FALSE );
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -36,7 +36,7 @@ uses
|
|||
type
|
||||
PDesktopFileEntry = ^TDesktopFileEntry;
|
||||
TDesktopFileEntry = record
|
||||
FileName: String;
|
||||
DesktopFilePath: String;
|
||||
MimeType: String;
|
||||
DisplayName: String;
|
||||
Comment: String;
|
||||
|
|
@ -56,7 +56,7 @@ function GetDesktopEntries(FileNames: TStringList): TList;
|
|||
implementation
|
||||
|
||||
uses
|
||||
uDCUtils, uIconTheme;
|
||||
uDCUtils, uIconTheme, uClipboard;
|
||||
|
||||
type
|
||||
PCDesktopFileEntry = ^TCDesktopFileEntry;
|
||||
|
|
@ -78,17 +78,127 @@ function mime_type_get_by_filename(filename: PChar; stat: Pointer) : PChar; cdec
|
|||
function mime_type_get_actions(mimeType: PChar): PPChar; cdecl; external libmime;
|
||||
function mime_type_locate_desktop_file(DirectoryToCheck: PChar; DesktopFileId: PChar): PChar; cdecl; external libmime;
|
||||
function mime_get_desktop_entry(DesktopFileName: PChar): TCDesktopFileEntry; cdecl; external libmime;
|
||||
function translate_app_exec_to_command_line(const app: PCDesktopFileEntry; file_list: PGList): PChar; cdecl; external libmime;
|
||||
|
||||
function TranslateAppExecToCmdLine(const entry: PDesktopFileEntry;
|
||||
const fileList: TStringList): String;
|
||||
var
|
||||
StartPos: Integer = 1;
|
||||
CurPos: Integer = 1;
|
||||
i: Integer;
|
||||
filesAdded: Boolean = False;
|
||||
begin
|
||||
// The .desktop standard does not recommend using % parameters inside quotes
|
||||
// in the Exec entry (the behaviour is undefined), so all those parameters
|
||||
// can be quoted using any method.
|
||||
Result := '';
|
||||
while CurPos <= Length(entry^.ExecWithParams) do
|
||||
begin
|
||||
if entry^.ExecWithParams[CurPos] = '%' then
|
||||
begin
|
||||
Result := Result + Copy(entry^.ExecWithParams, StartPos, CurPos - StartPos);
|
||||
Inc(CurPos);
|
||||
|
||||
if CurPos <= Length(entry^.ExecWithParams) then
|
||||
case entry^.ExecWithParams[CurPos] of
|
||||
'U':
|
||||
begin
|
||||
for i := 0 to fileList.Count - 1 do
|
||||
begin
|
||||
if i <> 0 then
|
||||
Result := Result + ' ';
|
||||
Result := Result + QuoteStr(URIEncode(fileList[i]));
|
||||
end;
|
||||
filesAdded := True;
|
||||
end;
|
||||
'u':
|
||||
if fileList.Count > 0 then
|
||||
begin
|
||||
Result := Result + QuoteStr(URIEncode(fileList[0]));
|
||||
filesAdded := True;
|
||||
end;
|
||||
'F':
|
||||
begin
|
||||
for i := 0 to fileList.Count - 1 do
|
||||
begin
|
||||
if i <> 0 then
|
||||
Result := Result + ' ';
|
||||
Result := Result + QuoteStr(fileList[i]);
|
||||
end;
|
||||
filesAdded := True;
|
||||
end;
|
||||
'f':
|
||||
if fileList.Count > 0 then
|
||||
begin
|
||||
Result := Result + QuoteStr(fileList[0]);
|
||||
filesAdded := True;
|
||||
end;
|
||||
'N': // deprecated
|
||||
begin
|
||||
for i := 0 to fileList.Count - 1 do
|
||||
begin
|
||||
if i <> 0 then
|
||||
Result := Result + ' ';
|
||||
Result := Result + QuoteStr(fileList[i]);
|
||||
end;
|
||||
filesAdded := True;
|
||||
end;
|
||||
'n': // deprecated
|
||||
if fileList.Count > 0 then
|
||||
begin
|
||||
Result := Result + QuoteStr(fileList[0]);
|
||||
filesAdded := True;
|
||||
end;
|
||||
'D': // deprecated
|
||||
begin
|
||||
for i := 0 to fileList.Count - 1 do
|
||||
begin
|
||||
if i <> 0 then
|
||||
Result := Result + ' ';
|
||||
Result := Result + QuoteStr(ExtractFilePath(fileList[i]));
|
||||
end;
|
||||
filesAdded := True;
|
||||
end;
|
||||
'd': // deprecated
|
||||
if fileList.Count > 0 then
|
||||
begin
|
||||
Result := Result + QuoteStr(ExtractFilePath(fileList[0]));
|
||||
filesAdded := True;
|
||||
end;
|
||||
'i':
|
||||
if entry^.IconName <> '' then
|
||||
Result := Result + '--icon ' + QuoteStr(entry^.IconName);
|
||||
'c':
|
||||
Result := Result + QuoteStr(entry^.DisplayName);
|
||||
'k':
|
||||
Result := Result + QuoteStr(entry^.DesktopFilePath);
|
||||
'%':
|
||||
Result := Result + '%';
|
||||
end;
|
||||
|
||||
Inc(CurPos);
|
||||
StartPos := CurPos;
|
||||
end
|
||||
else
|
||||
Inc(CurPos);
|
||||
end;
|
||||
|
||||
if (StartPos <> CurPos) then
|
||||
Result := Result + Copy(entry^.ExecWithParams, StartPos, CurPos - StartPos);
|
||||
|
||||
if not filesAdded then
|
||||
begin
|
||||
for i := 0 to fileList.Count - 1 do
|
||||
Result := Result + ' ' + QuoteStr(fileList[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetDesktopEntries(FileNames: TStringList): TList;
|
||||
var
|
||||
mimeType: PChar;
|
||||
actions: PPChar;
|
||||
desktopFile: PChar;
|
||||
i, j: Integer;
|
||||
i: Integer;
|
||||
app: TCDesktopFileEntry;
|
||||
list: PGList = nil;
|
||||
exec: PChar;
|
||||
Entry: PDesktopFileEntry;
|
||||
begin
|
||||
if FileNames.Count = 0 then
|
||||
|
|
@ -107,23 +217,21 @@ begin
|
|||
i := 0;
|
||||
while (actions[i] <> nil) and (actions[i] <> '') do
|
||||
begin
|
||||
for j := 0 to FileNames.Count - 1 do
|
||||
begin
|
||||
list := g_list_append(list, PChar(FileNames[j]));
|
||||
end;
|
||||
|
||||
desktopFile := mime_type_locate_desktop_file(nil, actions[i]);
|
||||
app := mime_get_desktop_entry(desktopFile);
|
||||
exec := translate_app_exec_to_command_line(@app, list);
|
||||
|
||||
New(Entry);
|
||||
|
||||
Entry^.DesktopFilePath := StrPas(desktopFile);
|
||||
Entry^.MimeType := StrPas(mimeType);
|
||||
Entry^.DisplayName := StrPas(app.DisplayName);
|
||||
Entry^.Comment := StrPas(app.Comment);
|
||||
Entry^.Exec := StrPas(Exec);
|
||||
Entry^.ExecWithParams := StrPas(app.Exec);
|
||||
Entry^.IconName := StrPas(app.IconName);
|
||||
Entry^.Terminal := app.Terminal;
|
||||
Entry^.Hidden := app.Hidden;
|
||||
// Set Exec as last because it uses other fields of Entry.
|
||||
Entry^.Exec := TranslateAppExecToCmdLine(Entry, Filenames);
|
||||
|
||||
{
|
||||
Some icon names in .desktop files are specified with an extension,
|
||||
|
|
@ -135,14 +243,11 @@ begin
|
|||
|
||||
Result.Add(Entry);
|
||||
|
||||
g_free(exec);
|
||||
g_free(desktopFile);
|
||||
g_free(app.DisplayName);
|
||||
g_free(app.Comment);
|
||||
g_free(app.Exec);
|
||||
g_free(app.IconName);
|
||||
g_list_free(list);
|
||||
list := nil;
|
||||
|
||||
i := i + 1;
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -210,8 +210,6 @@ var
|
|||
ExecCmd: String;
|
||||
begin
|
||||
ExecCmd := (Sender as TMenuItem).Hint;
|
||||
// Special case for file names containing ' char
|
||||
ExecCmd:= StringReplace(ExecCmd, '''\''''', '\''', [rfReplaceAll]);
|
||||
ExecCmdFork(ExecCmd);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue