Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
f2686c7c
Commit
f2686c7c
authored
Jul 19, 2006
by
Mikołaj Zalewski
Committed by
Alexandre Julliard
Jul 31, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shell32: Add trashing support functions.
parent
ca7de052
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
722 additions
and
1 deletion
+722
-1
Makefile.in
dlls/shell32/Makefile.in
+3
-1
trash.c
dlls/shell32/trash.c
+308
-0
xdg.c
dlls/shell32/xdg.c
+372
-0
xdg.h
dlls/shell32/xdg.h
+39
-0
No files found.
dlls/shell32/Makefile.in
View file @
f2686c7c
...
@@ -48,7 +48,9 @@ C_SRCS = \
...
@@ -48,7 +48,9 @@ C_SRCS = \
shpolicy.c
\
shpolicy.c
\
shv_bg_cmenu.c
\
shv_bg_cmenu.c
\
shv_item_cmenu.c
\
shv_item_cmenu.c
\
systray.c
systray.c
\
trash.c
\
xdg.c
RC_SRCS
=
shres.rc
RC_SRCS
=
shres.rc
RC_BINSRC
=
shres.rc
RC_BINSRC
=
shres.rc
...
...
dlls/shell32/trash.c
0 → 100644
View file @
f2686c7c
/*
* The freedesktop.org Trash, implemented using the 0.7 spec version
* (see http://www.ramendik.ru/docs/trashspec.html)
*
* Copyright (C) 2006 Mikolaj Zalewski
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winreg.h"
#include "shlwapi.h"
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include "wine/debug.h"
#include "shell32_main.h"
#include "xdg.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
trash
);
static
CRITICAL_SECTION
TRASH_Creating
;
static
CRITICAL_SECTION_DEBUG
TRASH_Creating_Debug
=
{
0
,
0
,
&
TRASH_Creating
,
{
&
TRASH_Creating_Debug
.
ProcessLocksList
,
&
TRASH_Creating_Debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)
__FILE__
": TRASH_Creating"
}
};
static
CRITICAL_SECTION
TRASH_Creating
=
{
&
TRASH_Creating_Debug
,
-
1
,
0
,
0
,
0
,
0
};
static
const
char
trashinfo_suffix
[]
=
".trashinfo"
;
static
const
char
trashinfo_header
[]
=
"[Trash Info]
\n
"
;
typedef
struct
{
char
*
info_dir
;
char
*
files_dir
;
dev_t
device
;
}
TRASH_BUCKET
;
static
TRASH_BUCKET
*
home_trash
=
NULL
;
static
char
*
init_home_dir
(
const
char
*
subpath
)
{
char
*
path
=
XDG_BuildPath
(
XDG_DATA_HOME
,
subpath
);
if
(
path
==
NULL
)
return
NULL
;
if
(
!
XDG_MakeDirs
(
path
))
{
ERR
(
"Couldn't create directory %s (errno=%d). Trash won't be available
\n
"
,
debugstr_a
(
path
),
errno
);
SHFree
(
path
);
path
=
NULL
;
}
return
path
;
}
static
TRASH_BUCKET
*
TRASH_CreateHomeBucket
(
void
)
{
TRASH_BUCKET
*
bucket
;
struct
stat
trash_stat
;
char
*
trash_path
=
NULL
;
bucket
=
SHAlloc
(
sizeof
(
TRASH_BUCKET
));
if
(
bucket
==
NULL
)
{
errno
=
ENOMEM
;
goto
error
;
}
memset
(
bucket
,
0
,
sizeof
(
*
bucket
));
bucket
->
info_dir
=
init_home_dir
(
"Trash/info/"
);
if
(
bucket
->
info_dir
==
NULL
)
goto
error
;
bucket
->
files_dir
=
init_home_dir
(
"Trash/files/"
);
if
(
bucket
->
files_dir
==
NULL
)
goto
error
;
trash_path
=
XDG_BuildPath
(
XDG_DATA_HOME
,
"Trash/"
);
if
(
stat
(
trash_path
,
&
trash_stat
)
==
-
1
)
goto
error
;
bucket
->
device
=
trash_stat
.
st_dev
;
SHFree
(
trash_path
);
return
bucket
;
error:
SHFree
(
trash_path
);
if
(
bucket
)
{
SHFree
(
bucket
->
info_dir
);
SHFree
(
bucket
->
files_dir
);
}
SHFree
(
bucket
);
return
NULL
;
}
static
BOOL
TRASH_EnsureInitialized
(
void
)
{
if
(
home_trash
==
NULL
)
{
EnterCriticalSection
(
&
TRASH_Creating
);
if
(
home_trash
==
NULL
)
home_trash
=
TRASH_CreateHomeBucket
();
LeaveCriticalSection
(
&
TRASH_Creating
);
}
if
(
home_trash
==
NULL
)
{
ERR
(
"Couldn't initialize home trash (errno=%d)
\n
"
,
errno
);
return
FALSE
;
}
return
TRUE
;
}
static
BOOL
file_good_for_bucket
(
TRASH_BUCKET
*
pBucket
,
struct
stat
*
file_stat
)
{
if
(
pBucket
->
device
!=
file_stat
->
st_dev
)
return
FALSE
;
return
S_ISREG
(
file_stat
->
st_mode
);
}
BOOL
TRASH_CanTrashFile
(
LPCWSTR
wszPath
)
{
struct
stat
file_stat
;
char
*
unix_path
;
TRACE
(
"(%s)
\n
"
,
debugstr_w
(
wszPath
));
if
(
!
TRASH_EnsureInitialized
())
return
FALSE
;
if
(
!
(
unix_path
=
wine_get_unix_file_name
(
wszPath
)))
return
FALSE
;
if
(
lstat
(
unix_path
,
&
file_stat
)
==-
1
)
{
HeapFree
(
GetProcessHeap
(),
0
,
unix_path
);
return
FALSE
;
}
HeapFree
(
GetProcessHeap
(),
0
,
unix_path
);
return
file_good_for_bucket
(
home_trash
,
&
file_stat
);
}
/*
* Try to create a single .trashinfo file. Return TRUE if successfull, else FALSE
*/
static
BOOL
try_create_trashinfo_file
(
const
char
*
info_dir
,
const
char
*
file_name
,
const
char
*
original_file_name
)
{
struct
tm
curr_time
;
time_t
curr_time_secs
;
char
datebuf
[
200
];
char
*
path
=
SHAlloc
(
strlen
(
info_dir
)
+
strlen
(
file_name
)
+
strlen
(
trashinfo_suffix
)
+
1
);
int
writer
=
-
1
;
if
(
path
==
NULL
)
return
FALSE
;
wsprintfA
(
path
,
"%s%s%s"
,
info_dir
,
file_name
,
trashinfo_suffix
);
TRACE
(
"Trying to create '%s'
\n
"
,
path
);
writer
=
open
(
path
,
O_CREAT
|
O_WRONLY
|
O_TRUNC
|
O_EXCL
,
0600
);
if
(
writer
==-
1
)
goto
error
;
write
(
writer
,
trashinfo_header
,
strlen
(
trashinfo_header
));
if
(
!
XDG_WriteDesktopStringEntry
(
writer
,
"Path"
,
XDG_URLENCODE
,
original_file_name
))
goto
error
;
time
(
&
curr_time_secs
);
localtime_r
(
&
curr_time_secs
,
&
curr_time
);
wnsprintfA
(
datebuf
,
200
,
"%04d-%02d-%02dT%02d:%02d:%02d"
,
curr_time
.
tm_year
+
1900
,
curr_time
.
tm_mon
+
1
,
curr_time
.
tm_mday
,
curr_time
.
tm_hour
,
curr_time
.
tm_min
,
curr_time
.
tm_sec
);
if
(
!
XDG_WriteDesktopStringEntry
(
writer
,
"DeletionDate"
,
0
,
datebuf
))
goto
error
;
close
(
writer
);
SHFree
(
path
);
return
TRUE
;
error:
if
(
writer
!=
-
1
)
{
close
(
writer
);
unlink
(
path
);
}
SHFree
(
path
);
return
FALSE
;
}
/*
* Try to create a .trashinfo file. This function will make several attempts with
* different filenames. It will return the filename that succeded or NULL if a file
* couldn't be created.
*/
static
char
*
create_trashinfo
(
const
char
*
info_dir
,
const
char
*
file_path
)
{
const
char
*
base_name
;
char
*
filename_buffer
;
unsigned
int
seed
=
(
unsigned
int
)
time
(
NULL
);
int
i
;
errno
=
ENOMEM
;
/* out-of-memory is the only case when errno isn't set */
base_name
=
strrchr
(
file_path
,
'/'
);
if
(
base_name
==
NULL
)
base_name
=
file_path
;
else
base_name
++
;
filename_buffer
=
SHAlloc
(
strlen
(
base_name
)
+
9
+
1
);
if
(
filename_buffer
==
NULL
)
return
NULL
;
lstrcpyA
(
filename_buffer
,
base_name
);
if
(
try_create_trashinfo_file
(
info_dir
,
filename_buffer
,
file_path
))
return
filename_buffer
;
for
(
i
=
0
;
i
<
30
;
i
++
)
{
sprintf
(
filename_buffer
,
"%s-%d"
,
base_name
,
i
+
1
);
if
(
try_create_trashinfo_file
(
info_dir
,
filename_buffer
,
file_path
))
return
filename_buffer
;
}
for
(
i
=
0
;
i
<
1000
;
i
++
)
{
sprintf
(
filename_buffer
,
"%s-%08x"
,
base_name
,
rand_r
(
&
seed
));
if
(
try_create_trashinfo_file
(
info_dir
,
filename_buffer
,
file_path
))
return
filename_buffer
;
}
WARN
(
"Couldn't create trashinfo after 1031 tries (errno=%d)
\n
"
,
errno
);
SHFree
(
filename_buffer
);
return
NULL
;
}
void
remove_trashinfo_file
(
const
char
*
info_dir
,
const
char
*
base_name
)
{
char
*
filename_buffer
;
filename_buffer
=
SHAlloc
(
lstrlenA
(
info_dir
)
+
lstrlenA
(
base_name
)
+
lstrlenA
(
trashinfo_suffix
)
+
1
);
if
(
filename_buffer
==
NULL
)
return
;
sprintf
(
filename_buffer
,
"%s%s%s"
,
info_dir
,
base_name
,
trashinfo_suffix
);
unlink
(
filename_buffer
);
SHFree
(
filename_buffer
);
}
static
BOOL
TRASH_MoveFileToBucket
(
TRASH_BUCKET
*
pBucket
,
const
char
*
unix_path
)
{
struct
stat
file_stat
;
char
*
trash_file_name
=
NULL
;
char
*
trash_path
=
NULL
;
BOOL
ret
=
TRUE
;
if
(
lstat
(
unix_path
,
&
file_stat
)
==-
1
)
return
FALSE
;
if
(
!
file_good_for_bucket
(
pBucket
,
&
file_stat
))
return
FALSE
;
trash_file_name
=
create_trashinfo
(
pBucket
->
info_dir
,
unix_path
);
if
(
trash_file_name
==
NULL
)
return
FALSE
;
trash_path
=
SHAlloc
(
strlen
(
pBucket
->
files_dir
)
+
strlen
(
trash_file_name
)
+
1
);
if
(
trash_path
==
NULL
)
goto
error
;
lstrcpyA
(
trash_path
,
pBucket
->
files_dir
);
lstrcatA
(
trash_path
,
trash_file_name
);
if
(
rename
(
unix_path
,
trash_path
)
==
0
)
{
TRACE
(
"rename succeded
\n
"
);
goto
cleanup
;
}
/* TODO: try to manually move the file */
ERR
(
"Couldn't move file
\n
"
);
error:
ret
=
FALSE
;
remove_trashinfo_file
(
pBucket
->
info_dir
,
trash_file_name
);
cleanup:
SHFree
(
trash_file_name
);
SHFree
(
trash_path
);
return
ret
;
}
BOOL
TRASH_TrashFile
(
LPCWSTR
wszPath
)
{
char
*
unix_path
;
BOOL
result
;
TRACE
(
"(%s)
\n
"
,
debugstr_w
(
wszPath
));
if
(
!
TRASH_EnsureInitialized
())
return
FALSE
;
if
(
!
(
unix_path
=
wine_get_unix_file_name
(
wszPath
)))
return
FALSE
;
result
=
TRASH_MoveFileToBucket
(
home_trash
,
unix_path
);
HeapFree
(
GetProcessHeap
(),
0
,
unix_path
);
return
result
;
}
dlls/shell32/xdg.c
0 → 100644
View file @
f2686c7c
/*
* Generic freedesktop.org support code
*
* Copyright (C) 2006 Mikolaj Zalewski
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "shell32_main.h"
#include "xdg.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
xdg
);
/*
* XDG paths implemented using Desktop Base Directory spec version 0.6
* (from http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html)
*/
static
CRITICAL_SECTION
XDG_PathsLock
;
static
CRITICAL_SECTION_DEBUG
XDG_PathsLock_Debug
=
{
0
,
0
,
&
XDG_PathsLock
,
{
&
XDG_PathsLock_Debug
.
ProcessLocksList
,
&
XDG_PathsLock_Debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)
__FILE__
": XDG_PathsLock"
}
};
static
CRITICAL_SECTION
XDG_PathsLock
=
{
&
XDG_PathsLock_Debug
,
-
1
,
0
,
0
,
0
,
0
};
typedef
struct
{
const
char
*
var_name
;
const
char
*
default_value
;
}
std_path
;
static
const
std_path
paths
[]
=
{
{
"XDG_DATA_HOME"
,
"$HOME/.local/share"
},
{
"XDG_CONFIG_HOME"
,
"$HOME/.config"
},
{
"XDG_DATA_DIRS"
,
"/usr/local/share:/usr/share"
},
{
"XDG_CONFIG_DIRS"
,
"/etc/xdg"
},
{
"XDG_CACHE_HOME"
,
"$HOME/.cache"
}
};
#define PATHS_COUNT (sizeof(paths)/sizeof(paths[0]))
/* will be filled with paths as they are computed */
static
const
char
*
path_values
[
PATHS_COUNT
]
=
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
static
char
*
load_path
(
int
path_id
)
{
char
*
env
=
getenv
(
paths
[
path_id
].
var_name
);
char
*
ret
;
if
(
env
!=
NULL
&&
env
[
0
]
==
'/'
)
{
ret
=
SHAlloc
(
strlen
(
env
)
+
1
);
if
(
ret
!=
NULL
)
lstrcpyA
(
ret
,
env
);
return
ret
;
}
if
(
memcmp
(
paths
[
path_id
].
default_value
,
"$HOME"
,
5
)
==
0
)
{
char
*
home
=
getenv
(
"HOME"
);
int
len
;
if
(
!
home
)
return
NULL
;
ret
=
SHAlloc
(
strlen
(
home
)
+
strlen
(
paths
[
path_id
].
default_value
)
-
5
+
1
);
if
(
ret
==
NULL
)
return
NULL
;
lstrcpyA
(
ret
,
home
);
len
=
strlen
(
ret
);
if
(
len
>
0
&&
ret
[
len
-
1
]
==
'/'
)
ret
[
--
len
]
=
0
;
lstrcatA
(
ret
,
paths
[
path_id
].
default_value
+
5
);
return
ret
;
}
ret
=
SHAlloc
(
strlen
(
paths
[
path_id
].
default_value
)
+
1
);
if
(
ret
!=
NULL
)
lstrcpyA
(
ret
,
env
);
return
ret
;
}
/******************************************************************************
* XDG_GetPath [internal]
*
* Get one of the XDG standard patch. The return value shouldn't be modified nor
* freed. A return value of NULL means that the memory is exhausted or the input
* is invalid
*
* For XDG_DATA_HOME, XDG_CONFIG_HOME and XDG_CACHE_HOME the result is a Unix path.
* For XDG_DATA_DIRS and XDG_CONFIG_DIRS the result is a colon-separated list of Unix
* paths
*
* The paths are guaranteed to start with '/'
*/
const
char
*
XDG_GetPath
(
int
path_id
)
{
if
(
path_id
>=
PATHS_COUNT
||
path_id
<
0
)
{
ERR
(
"Invalid path_id %d
\n
"
,
path_id
);
return
NULL
;
}
if
(
path_values
[
path_id
]
!=
NULL
)
return
path_values
[
path_id
];
EnterCriticalSection
(
&
XDG_PathsLock
);
if
(
path_values
[
path_id
]
==
NULL
)
path_values
[
path_id
]
=
load_path
(
path_id
);
LeaveCriticalSection
(
&
XDG_PathsLock
);
return
path_values
[
path_id
];
}
/******************************************************************************
* XDG_GetPath [internal]
*
* Build a string with a subpath of one of the XDG standard paths.
* The root can be one of XDG_DATA_HOME, XDG_CONFIG_HOME and XDG_CACHE_HOME.
* The subpath is a path relative to that root (it shouldn't start with a slash)
*
* The returned path should be freed with SHFree. A return of NULL means that the
* memory is exhausted or the parameters are invalid
*/
char
*
XDG_BuildPath
(
int
root_id
,
const
char
*
subpath
)
{
const
char
*
root_path
=
XDG_GetPath
(
root_id
);
char
*
ret_buffer
;
int
root_len
;
if
(
root_id
==
XDG_DATA_DIRS
||
root_id
==
XDG_CONFIG_DIRS
)
{
ERR
(
"Invalid path id %d
\n
"
,
root_id
);
return
NULL
;
}
if
(
root_path
==
NULL
)
return
NULL
;
root_len
=
strlen
(
root_path
);
if
(
root_path
[
root_len
-
1
]
==
'/'
)
root_len
--
;
ret_buffer
=
SHAlloc
(
root_len
+
1
+
strlen
(
subpath
)
+
1
);
if
(
ret_buffer
==
NULL
)
return
NULL
;
lstrcpyA
(
ret_buffer
,
root_path
);
ret_buffer
[
root_len
]
=
'/'
;
lstrcpyA
(
ret_buffer
+
root_len
+
1
,
subpath
);
return
ret_buffer
;
}
/******************************************************************************
* XDG_MakeDirs [internal]
*
* Checks that all the directories on the specified path exists. If some don't exists
* they are created with mask 0700 as required by many the freedeskop.org specs.
* If the path doesn't end with '/' it is assumed to be a path to a file and the last
* segment is not checked
*
* In case of a failure the errno is always set and can be used e.g for debugging
*
* RETURNS
* TRUE on success, FALSE on error
*/
BOOL
XDG_MakeDirs
(
const
char
*
path
)
{
int
last_slash
=
0
;
BOOL
success
=
TRUE
;
struct
stat
tmp
;
char
*
buffer
=
SHAlloc
(
strlen
(
path
)
+
1
);
if
(
buffer
==
NULL
)
{
errno
=
ENOMEM
;
return
FALSE
;
}
lstrcpyA
(
buffer
,
path
);
TRACE
(
"(%s)
\n
"
,
debugstr_a
(
path
));
while
(
1
)
{
char
*
slash
=
strchr
(
buffer
+
last_slash
+
1
,
'/'
);
if
(
slash
==
NULL
)
break
;
/* cut the string at that position and create the directory if it doesn't exist */
*
slash
=
0
;
TRACE
(
"Checking path %s
\n
"
,
debugstr_a
(
buffer
));
success
=
(
stat
(
buffer
,
&
tmp
)
==
0
);
if
(
!
success
&&
errno
==
ENOENT
)
{
TRACE
(
"Creating
\n
"
);
success
=
(
mkdir
(
buffer
,
0700
)
==
0
);
}
if
(
!
success
)
{
WARN
(
"Couldn't process directory %s (errno=%d)
\n
"
,
debugstr_a
(
buffer
),
errno
);
break
;
}
*
slash
=
'/'
;
last_slash
=
slash
-
buffer
;
}
SHFree
(
buffer
);
return
success
;
}
/*
* .desktop files functions
*/
/******************************************************************************
* dskentry_encode [internal]
*
* Escape the characters that can't be present in a desktop entry value like \n, leading
* spaces etc. The output parameter may be NULL. Then only the number of characters will
* be computers.
*
* RETURNS
* The number of characters after escaping the special characters, including the
* terminating NUL.
*/
static
int
dskentry_encode
(
const
char
*
value
,
char
*
output
)
{
int
only_spc
=
TRUE
;
int
num_written
=
0
;
const
char
*
c
;
for
(
c
=
value
;
*
c
;
c
++
)
{
if
(
only_spc
&&
*
c
==
' '
)
{
if
(
output
)
{
*
(
output
++
)
=
'\\'
;
*
(
output
++
)
=
's'
;
}
num_written
+=
2
;
continue
;
}
only_spc
=
FALSE
;
if
(
*
c
==
'\t'
||
*
c
==
'\r'
||
*
c
==
'\n'
||
*
c
==
'\\'
)
{
if
(
output
)
{
*
(
output
++
)
=
'\\'
;
if
(
*
c
==
'\t'
)
*
(
output
++
)
=
't'
;
if
(
*
c
==
'\r'
)
*
(
output
++
)
=
'r'
;
if
(
*
c
==
'\n'
)
*
(
output
++
)
=
'n'
;
if
(
*
c
==
'\\'
)
*
(
output
++
)
=
'\\'
;
}
num_written
+=
2
;
}
else
{
if
(
output
)
*
(
output
++
)
=*
c
;
num_written
++
;
}
}
if
(
output
)
*
(
output
++
)
=
0
;
num_written
++
;
return
num_written
;
}
/******************************************************************************
* url_encode [internal]
*
* URL-encode the given string (i.e. use escape codes like %20). Note that an
* URL-encoded string can be used as a value in desktop entry files as all
* unsafe characters are escaped.
*
* The output can be NULL. Then only the number of characters will be counted
*
* RETURNS
* The number of characters after escaping the special characters, including the
* terminating NUL.
*/
static
int
url_encode
(
const
char
*
value
,
char
*
output
)
{
static
const
char
*
unsafechars
=
"^&`{}|[]'<>
\\
#%
\"
+"
;
static
const
char
*
hexchars
=
"0123456789ABCDEF"
;
int
num_written
=
0
;
const
char
*
c
;
for
(
c
=
value
;
*
c
;
c
++
)
{
if
(
*
c
<=
0x20
||
*
c
>=
0x7f
||
strchr
(
unsafechars
,
*
c
))
{
if
(
output
)
{
*
(
output
++
)
=
'%'
;
*
(
output
++
)
=
hexchars
[(
unsigned
)(
*
c
)
/
16
];
*
(
output
++
)
=
hexchars
[(
unsigned
)(
*
c
)
%
16
];
}
num_written
+=
3
;
}
else
{
if
(
output
)
*
(
output
++
)
=
*
c
;
num_written
++
;
}
}
if
(
output
)
*
(
output
++
)
=
0
;
num_written
++
;
return
num_written
;
}
static
int
escape_value
(
const
char
*
value
,
DWORD
dwFlags
,
char
*
output
)
{
if
(
dwFlags
&
XDG_URLENCODE
)
return
url_encode
(
value
,
output
);
return
dskentry_encode
(
value
,
output
);
}
/******************************************************************************
* XDG_WriteDesktopStringEntry [internal]
*
* Writes a key=value pair into the specified file descriptor.
*
* RETURNS
* TRUE on success, else FALSE
*/
BOOL
XDG_WriteDesktopStringEntry
(
int
writer
,
const
char
*
keyName
,
DWORD
dwFlags
,
const
char
*
value
)
{
int
keyLen
=
lstrlenA
(
keyName
);
int
valueLen
=
escape_value
(
value
,
dwFlags
,
NULL
);
char
*
string
=
SHAlloc
(
keyLen
+
1
+
valueLen
);
BOOL
ret
;
if
(
string
==
NULL
)
return
FALSE
;
lstrcpyA
(
string
,
keyName
);
string
[
keyLen
]
=
'='
;
escape_value
(
value
,
dwFlags
,
string
+
keyLen
+
1
);
string
[
keyLen
+
1
+
valueLen
-
1
]
=
'\n'
;
/* -1 because valueLen contains the last NUL character */
ret
=
(
write
(
writer
,
string
,
keyLen
+
1
+
valueLen
)
!=-
1
);
SHFree
(
string
);
return
ret
;
}
dlls/shell32/xdg.h
0 → 100644
View file @
f2686c7c
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __XDG_H__
#define __XDG_H__
/*
* XDG directories access
*/
#define XDG_DATA_HOME 0
#define XDG_CONFIG_HOME 1
#define XDG_DATA_DIRS 2
#define XDG_CONFIG_DIRS 3
#define XDG_CACHE_HOME 4
const
char
*
XDG_GetPath
(
int
path_id
);
char
*
XDG_BuildPath
(
int
root_id
,
const
char
*
subpath
);
int
XDG_MakeDirs
(
const
char
*
path
);
#define XDG_URLENCODE 0x1
BOOL
XDG_WriteDesktopStringEntry
(
int
fd
,
const
char
*
keyName
,
DWORD
dwFlags
,
const
char
*
value
);
/* implemented in trash.c */
BOOL
TRASH_CanTrashFile
(
LPCWSTR
wszPath
);
BOOL
TRASH_TrashFile
(
LPCWSTR
wszPath
);
#endif
/* ndef __XDG_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment