1999-12-17 04:48:16 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1999-12-17 04:48:16 +03:00
SMB backend for the Common UNIX Printing System ( " CUPS " )
Copyright 1999 by Easy Software Products
Copyright Andrew Tridgell 1994 - 1998
2002-07-15 14:35:28 +04:00
Copyright Andrew Bartlett 2002
2005-05-09 20:04:27 +04:00
Copyright Rodrigo Fernandez - Vizarra 2005
1999-12-17 04:48:16 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1999-12-17 04:48:16 +03:00
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1999-12-17 04:48:16 +03:00
*/
2005-05-09 20:04:27 +04:00
# include "includes.h"
# define TICKET_CC_DIR " / tmp"
# define CC_PREFIX "krb5cc_" /* prefix of the ticket cache */
# define CC_MAX_FILE_LEN 24
2005-06-24 19:13:25 +04:00
# define CC_MAX_FILE_PATH_LEN (sizeof(TICKET_CC_DIR)-1)+ CC_MAX_FILE_LEN+2
2005-05-09 20:04:27 +04:00
# define OVERWRITE 1
2005-06-24 19:13:25 +04:00
# define KRB5CCNAME "KRB5CCNAME"
2005-11-18 17:33:12 +03:00
# define MAX_RETRY_CONNECT 3
1999-12-17 04:48:16 +03:00
/*
* Globals . . .
*/
2007-10-19 04:40:25 +04:00
extern bool in_client ; /* Boolean for client library */
1999-12-17 04:48:16 +03:00
/*
* Local functions . . .
*/
2001-03-16 22:17:04 +03:00
static void list_devices ( void ) ;
2005-05-09 20:04:27 +04:00
static struct cli_state * smb_complete_connection ( const char * , const char * , int , const char * , const char * , const char * , const char * , int ) ;
static struct cli_state * smb_connect ( const char * , const char * , int , const char * , const char * , const char * , const char * ) ;
1999-12-17 04:48:16 +03:00
static int smb_print ( struct cli_state * , char * , FILE * ) ;
2007-06-16 22:54:13 +04:00
static char * uri_unescape_alloc ( const char * ) ;
1999-12-17 04:48:16 +03:00
/*
* ' main ( ) ' - Main entry for SMB backend .
*/
int /* O - Exit status */
main ( int argc , /* I - Number of command-line arguments */
char * argv [ ] ) /* I - Command-line arguments */
{
int i ; /* Looping var */
int copies ; /* Number of copies */
2004-05-30 15:59:12 +04:00
int port ; /* Port number */
1999-12-17 04:48:16 +03:00
char uri [ 1024 ] , /* URI */
* sep , /* Pointer to separator */
2007-06-16 22:54:13 +04:00
* tmp , * tmp2 , /* Temp pointers to do escaping */
2003-01-03 11:28:12 +03:00
* password ; /* Password */
2007-06-16 22:54:13 +04:00
char * username , /* Username */
1999-12-17 04:48:16 +03:00
* server , /* Server name */
* printer ; /* Printer name */
2002-11-13 02:20:50 +03:00
const char * workgroup ; /* Workgroup */
1999-12-17 04:48:16 +03:00
FILE * fp ; /* File to print */
2007-11-09 05:50:07 +03:00
int status = 1 ; /* Status of LPD job */
1999-12-17 04:48:16 +03:00
struct cli_state * cli ; /* SMB interface */
2005-09-30 21:13:37 +04:00
char null_str [ 1 ] ;
2005-11-18 17:33:12 +03:00
int tries = 0 ;
2006-06-28 08:30:51 +04:00
const char * dev_uri ;
2007-11-09 05:50:07 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2005-09-30 21:13:37 +04:00
null_str [ 0 ] = ' \0 ' ;
1999-12-17 04:48:16 +03:00
/* we expect the URI in argv[0]. Detect the case where it is in argv[1] and cope */
if ( argc > 2 & & strncmp ( argv [ 0 ] , " smb:// " , 6 ) & & ! strncmp ( argv [ 1 ] , " smb:// " , 6 ) ) {
argv + + ;
argc - - ;
}
2001-03-16 22:17:04 +03:00
if ( argc = = 1 )
{
/*
* NEW ! In CUPS 1.1 the backends are run with no arguments to list the
* available devices . These can be devices served by this backend
* or any other backends ( i . e . you can have an SNMP backend that
* is only used to enumerate the available network printers . . . : )
*/
list_devices ( ) ;
2007-11-09 05:50:07 +03:00
status = 0 ;
goto done ;
2001-03-16 22:17:04 +03:00
}
1999-12-17 04:48:16 +03:00
if ( argc < 6 | | argc > 7 )
{
fprintf ( stderr , " Usage: %s [DEVICE_URI] job-id user title copies options [file] \n " ,
argv [ 0 ] ) ;
fputs ( " The DEVICE_URI environment variable can also contain the \n " , stderr ) ;
fputs ( " destination printer: \n " , stderr ) ;
fputs ( " \n " , stderr ) ;
2004-05-30 15:59:12 +04:00
fputs ( " smb://[username:password@][workgroup/]server[:port]/printer \n " , stderr ) ;
2007-11-09 05:50:07 +03:00
goto done ;
1999-12-17 04:48:16 +03:00
}
/*
* If we have 7 arguments , print the file named on the command - line .
* Otherwise , print data from stdin . . .
*/
2005-05-09 20:04:27 +04:00
1999-12-17 04:48:16 +03:00
if ( argc = = 6 )
{
/*
* Print from Copy stdin to a temporary file . . .
*/
fp = stdin ;
copies = 1 ;
}
else if ( ( fp = fopen ( argv [ 6 ] , " rb " ) ) = = NULL )
{
perror ( " ERROR: Unable to open print file " ) ;
2007-11-09 05:50:07 +03:00
goto done ;
1999-12-17 04:48:16 +03:00
}
else
copies = atoi ( argv [ 4 ] ) ;
/*
2001-07-03 04:52:56 +04:00
* Find the URI . . .
1999-12-17 04:48:16 +03:00
*/
2006-06-28 08:30:51 +04:00
dev_uri = getenv ( " DEVICE_URI " ) ;
if ( dev_uri )
strncpy ( uri , dev_uri , sizeof ( uri ) - 1 ) ;
2004-10-27 04:52:12 +04:00
else if ( strncmp ( argv [ 0 ] , " smb:// " , 6 ) = = 0 )
strncpy ( uri , argv [ 0 ] , sizeof ( uri ) - 1 ) ;
1999-12-17 04:48:16 +03:00
else
{
2004-10-27 04:52:12 +04:00
fputs ( " ERROR: No device URI found in DEVICE_URI environment variable or argv[0] ! \n " , stderr ) ;
2007-11-09 05:50:07 +03:00
goto done ;
1999-12-17 04:48:16 +03:00
}
uri [ sizeof ( uri ) - 1 ] = ' \0 ' ;
/*
* Extract the destination from the URI . . .
*/
2001-07-04 11:36:09 +04:00
if ( ( sep = strrchr_m ( uri , ' @ ' ) ) ! = NULL )
1999-12-17 04:48:16 +03:00
{
2007-06-16 22:54:13 +04:00
tmp = uri + 6 ;
1999-12-17 04:48:16 +03:00
* sep + + = ' \0 ' ;
2007-06-16 22:54:13 +04:00
/* username is in tmp */
1999-12-17 04:48:16 +03:00
server = sep ;
/*
* Extract password as needed . . .
*/
2007-06-16 22:54:13 +04:00
if ( ( tmp2 = strchr_m ( tmp , ' : ' ) ) ! = NULL ) {
* tmp2 + + = ' \0 ' ;
password = uri_unescape_alloc ( tmp2 ) ;
} else {
2005-09-30 21:13:37 +04:00
password = null_str ;
2007-06-16 22:54:13 +04:00
}
username = uri_unescape_alloc ( tmp ) ;
1999-12-17 04:48:16 +03:00
}
else
{
2005-09-30 21:13:37 +04:00
username = null_str ;
password = null_str ;
1999-12-17 04:48:16 +03:00
server = uri + 6 ;
}
2007-06-16 22:54:13 +04:00
tmp = server ;
if ( ( sep = strchr_m ( tmp , ' / ' ) ) = = NULL )
1999-12-17 04:48:16 +03:00
{
fputs ( " ERROR: Bad URI - need printer name! \n " , stderr ) ;
2007-11-09 05:50:07 +03:00
goto done ;
1999-12-17 04:48:16 +03:00
}
* sep + + = ' \0 ' ;
2007-06-16 22:54:13 +04:00
tmp2 = sep ;
1999-12-17 04:48:16 +03:00
2007-06-16 22:54:13 +04:00
if ( ( sep = strchr_m ( tmp2 , ' / ' ) ) ! = NULL )
1999-12-17 04:48:16 +03:00
{
/*
* Convert to smb : //[username:password@]workgroup/server/printer...
*/
* sep + + = ' \0 ' ;
2007-06-16 22:54:13 +04:00
workgroup = uri_unescape_alloc ( tmp ) ;
server = uri_unescape_alloc ( tmp2 ) ;
printer = uri_unescape_alloc ( sep ) ;
1999-12-17 04:48:16 +03:00
}
2007-06-16 22:54:13 +04:00
else {
1999-12-17 04:48:16 +03:00
workgroup = NULL ;
2007-06-16 22:54:13 +04:00
server = uri_unescape_alloc ( tmp ) ;
printer = uri_unescape_alloc ( tmp2 ) ;
}
2004-05-30 15:59:12 +04:00
if ( ( sep = strrchr_m ( server , ' : ' ) ) ! = NULL )
{
* sep + + = ' \0 ' ;
1999-12-17 04:48:16 +03:00
2004-05-30 15:59:12 +04:00
port = atoi ( sep ) ;
}
2007-06-16 22:54:13 +04:00
else
2004-05-30 15:59:12 +04:00
port = 0 ;
1999-12-17 04:48:16 +03:00
/*
* Setup the SAMBA server state . . .
*/
setup_logging ( " smbspool " , True ) ;
in_client = True ; /* Make sure that we tell lp_load we are */
2006-05-13 03:05:01 +04:00
load_case_tables ( ) ;
2007-12-10 22:30:37 +03:00
if ( ! lp_load ( get_dyn_CONFIGFILE ( ) , True , False , False , True ) )
1999-12-17 04:48:16 +03:00
{
2007-12-10 22:30:37 +03:00
fprintf ( stderr , " ERROR: Can't load %s - run testparm to debug it \n " , get_dyn_CONFIGFILE ( ) ) ;
2007-11-09 05:50:07 +03:00
goto done ;
1999-12-17 04:48:16 +03:00
}
if ( workgroup = = NULL )
workgroup = lp_workgroup ( ) ;
load_interfaces ( ) ;
2001-07-03 04:52:56 +04:00
do
1999-12-17 04:48:16 +03:00
{
2005-05-09 20:04:27 +04:00
if ( ( cli = smb_connect ( workgroup , server , port , printer , username , password , argv [ 2 ] ) ) = = NULL )
2001-07-03 04:52:56 +04:00
{
if ( getenv ( " CLASS " ) = = NULL )
{
2005-11-18 17:33:12 +03:00
fprintf ( stderr , " ERROR: Unable to connect to CIFS host, will retry in 60 seconds... \n " ) ;
2005-08-29 17:10:20 +04:00
sleep ( 60 ) ; /* should just waiting and retrying fix authentication ??? */
2005-11-18 17:33:12 +03:00
tries + + ;
2001-07-03 04:52:56 +04:00
}
else
{
2005-11-18 17:33:12 +03:00
fprintf ( stderr , " ERROR: Unable to connect to CIFS host, trying next printer... \n " ) ;
2007-11-09 05:50:07 +03:00
goto done ;
2001-07-03 04:52:56 +04:00
}
}
1999-12-17 04:48:16 +03:00
}
2005-11-18 17:33:12 +03:00
while ( ( cli = = NULL ) & & ( tries < MAX_RETRY_CONNECT ) ) ;
if ( cli = = NULL ) {
fprintf ( stderr , " ERROR: Unable to connect to CIFS host after (tried %d times) \n " , tries ) ;
2007-11-09 05:50:07 +03:00
goto done ;
2005-11-18 17:33:12 +03:00
}
2001-07-03 04:52:56 +04:00
/*
* Now that we are connected to the server , ignore SIGTERM so that we
* can finish out any page data the driver sends ( e . g . to eject the
* current page . . . Only ignore SIGTERM if we are printing data from
* stdin ( otherwise you can ' t cancel raw jobs . . . )
*/
if ( argc < 7 )
CatchSignal ( SIGTERM , SIG_IGN ) ;
1999-12-17 04:48:16 +03:00
/*
* Queue the job . . .
*/
for ( i = 0 ; i < copies ; i + + )
if ( ( status = smb_print ( cli , argv [ 3 ] /* title */ , fp ) ) ! = 0 )
break ;
cli_shutdown ( cli ) ;
/*
* Return the queue status . . .
*/
2007-11-09 05:50:07 +03:00
done :
TALLOC_FREE ( frame ) ;
1999-12-17 04:48:16 +03:00
return ( status ) ;
}
2001-03-16 22:17:04 +03:00
/*
* ' list_devices ( ) ' - List the available printers seen on the network . . .
*/
static void
list_devices ( void )
{
/*
* Eventually , search the local workgroup for available hosts and printers .
*/
puts ( " network smb \" Unknown \" \" Windows Printer via SAMBA \" " ) ;
}
1999-12-17 04:48:16 +03:00
/*
2005-05-09 20:04:27 +04:00
* get the name of the newest ticket cache for the uid user .
* pam_krb5 defines a non default ticket cache for each user
1999-12-17 04:48:16 +03:00
*/
2005-05-09 20:04:27 +04:00
static
char * get_ticket_cache ( uid_t uid )
{
2006-03-10 16:12:38 +03:00
char * ticket_file = NULL ;
2005-08-24 01:29:37 +04:00
SMB_STRUCT_DIR * tcdir ; /* directory where ticket caches are stored */
2005-05-09 20:04:27 +04:00
SMB_STRUCT_DIRENT * dirent ; /* directory entry */
char * filename = NULL ; /* holds file names on the tmp directory */
SMB_STRUCT_STAT buf ;
char user_cache_prefix [ CC_MAX_FILE_LEN ] ;
char file_path [ CC_MAX_FILE_PATH_LEN ] ;
time_t t = 0 ;
2006-03-10 16:12:38 +03:00
2005-05-09 20:04:27 +04:00
snprintf ( user_cache_prefix , CC_MAX_FILE_LEN , " %s%d " , CC_PREFIX , uid ) ;
2005-08-24 01:29:37 +04:00
tcdir = sys_opendir ( TICKET_CC_DIR ) ;
2005-05-09 20:04:27 +04:00
if ( tcdir = = NULL )
return NULL ;
while ( ( dirent = sys_readdir ( tcdir ) ) )
{
filename = dirent - > d_name ;
snprintf ( file_path , CC_MAX_FILE_PATH_LEN , " %s/%s " , TICKET_CC_DIR , filename ) ;
if ( sys_stat ( file_path , & buf ) = = 0 )
{
if ( ( buf . st_uid = = uid ) & & ( S_ISREG ( buf . st_mode ) ) )
{
/*
* check the user id of the file to prevent denial of
* service attacks by creating fake ticket caches for the
* user
*/
if ( strstr ( filename , user_cache_prefix ) )
{
if ( buf . st_mtime > t )
{
/*
* a newer ticket cache found
*/
free ( ticket_file ) ;
ticket_file = SMB_STRDUP ( file_path ) ;
t = buf . st_mtime ;
}
}
}
}
}
1999-12-17 04:48:16 +03:00
2005-08-24 01:29:37 +04:00
sys_closedir ( tcdir ) ;
2005-05-09 20:04:27 +04:00
if ( ticket_file = = NULL )
{
/* no ticket cache found */
fprintf ( stderr , " ERROR: No ticket cache found for userid=%d \n " , uid ) ;
return NULL ;
}
return ticket_file ;
}
static struct cli_state
* smb_complete_connection ( const char * myname ,
const char * server ,
int port ,
const char * username ,
const char * password ,
const char * workgroup ,
const char * share ,
int flags )
1999-12-17 04:48:16 +03:00
{
2005-05-09 20:04:27 +04:00
struct cli_state * cli ; /* New connection */
2002-07-15 14:35:28 +04:00
NTSTATUS nt_status ;
2005-05-09 20:04:27 +04:00
/* Start the SMB connection */
nt_status = cli_start_connection ( & cli , myname , server , NULL , port ,
Undefined , flags , NULL ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) )
{
return NULL ;
}
2006-03-11 02:22:38 +03:00
/* We pretty much guarentee password must be valid or a pointer
to a 0 char . */
if ( ! password ) {
return NULL ;
}
2005-05-09 20:04:27 +04:00
if ( ( username ) & & ( * username ) & &
2006-03-11 02:22:38 +03:00
( strlen ( password ) = = 0 ) & &
2005-05-09 20:04:27 +04:00
( cli - > use_kerberos ) )
{
/* Use kerberos authentication */
struct passwd * pw ;
char * cache_file ;
if ( ! ( pw = sys_getpwnam ( username ) ) ) {
fprintf ( stderr , " ERROR Can not get %s uid \n " , username ) ;
cli_shutdown ( cli ) ;
return NULL ;
}
/*
* Get the ticket cache of the user to set KRB5CCNAME env
* variable
*/
cache_file = get_ticket_cache ( pw - > pw_uid ) ;
if ( cache_file = = NULL )
{
fprintf ( stderr , " ERROR: Can not get the ticket cache for %s \n " , username ) ;
cli_shutdown ( cli ) ;
return NULL ;
}
if ( setenv ( KRB5CCNAME , cache_file , OVERWRITE ) < 0 )
{
fprintf ( stderr , " ERROR: Can not add KRB5CCNAME to the environment " ) ;
cli_shutdown ( cli ) ;
free ( cache_file ) ;
return NULL ;
}
free ( cache_file ) ;
/*
* Change the UID of the process to be able to read the kerberos
* ticket cache
*/
setuid ( pw - > pw_uid ) ;
}
2006-08-16 21:14:16 +04:00
if ( ! NT_STATUS_IS_OK ( cli_session_setup ( cli , username ,
password , strlen ( password ) + 1 ,
password , strlen ( password ) + 1 ,
workgroup ) ) )
2005-05-09 20:04:27 +04:00
{
fprintf ( stderr , " ERROR: Session setup failed: %s \n " , cli_errstr ( cli ) ) ;
if ( NT_STATUS_V ( cli_nt_error ( cli ) ) = =
NT_STATUS_V ( NT_STATUS_MORE_PROCESSING_REQUIRED ) )
{
fprintf ( stderr , " did you forget to run kinit? \n " ) ;
}
cli_shutdown ( cli ) ;
return NULL ;
}
2005-08-29 17:10:20 +04:00
if ( ! cli_send_tconX ( cli , share , " ????? " , password , strlen ( password ) + 1 ) )
2005-05-09 20:04:27 +04:00
{
2005-08-29 17:10:20 +04:00
fprintf ( stderr , " ERROR: Tree connect failed (%s) \n " , cli_errstr ( cli ) ) ;
2005-05-09 20:04:27 +04:00
cli_shutdown ( cli ) ;
return NULL ;
}
return cli ;
}
/*
* ' smb_connect ( ) ' - Return a connection to a server .
*/
static struct cli_state * /* O - SMB connection */
smb_connect ( const char * workgroup , /* I - Workgroup */
const char * server , /* I - Server */
const int port , /* I - Port */
const char * share , /* I - Printer */
const char * username , /* I - Username */
const char * password , /* I - Password */
const char * jobusername ) /* I - User who issued the print job */
{
struct cli_state * cli ; /* New connection */
2007-11-09 05:50:07 +03:00
char * myname = NULL ; /* Client name */
2005-12-02 13:26:29 +03:00
struct passwd * pwd ;
1999-12-17 04:48:16 +03:00
/*
* Get the names and addresses of the client and server . . .
*/
2007-11-09 05:50:07 +03:00
myname = get_myname ( talloc_tos ( ) ) ;
if ( ! myname ) {
return NULL ;
}
2005-05-09 20:04:27 +04:00
2005-09-27 23:18:20 +04:00
/* See if we have a username first. This is for backwards compatible
behavior with 3.0 .14 a */
if ( username & & * username )
2005-05-09 20:04:27 +04:00
{
cli = smb_complete_connection ( myname , server , port , username ,
password , workgroup , share , 0 ) ;
2005-09-27 23:18:20 +04:00
if ( cli )
return cli ;
1999-12-17 04:48:16 +03:00
}
2005-05-09 20:04:27 +04:00
/*
* Try to use the user kerberos credentials ( if any ) to authenticate
*/
cli = smb_complete_connection ( myname , server , port , jobusername , " " ,
workgroup , share ,
CLI_FULL_CONNECTION_USE_KERBEROS ) ;
if ( cli ) { return cli ; }
2005-12-02 13:26:29 +03:00
/* give a chance for a passwordless NTLMSSP session setup */
pwd = getpwuid ( geteuid ( ) ) ;
if ( pwd = = NULL ) {
return NULL ;
}
cli = smb_complete_connection ( myname , server , port , pwd - > pw_name , " " ,
workgroup , share , 0 ) ;
if ( cli ) { return cli ; }
2005-05-09 20:04:27 +04:00
/*
* last try . Use anonymous authentication
*/
2005-12-02 13:26:29 +03:00
2005-05-09 20:04:27 +04:00
cli = smb_complete_connection ( myname , server , port , " " , " " ,
workgroup , share , 0 ) ;
2002-08-17 21:00:51 +04:00
/*
* Return the new connection . . .
*/
2005-05-09 20:04:27 +04:00
return ( cli ) ;
1999-12-17 04:48:16 +03:00
}
/*
* ' smb_print ( ) ' - Queue a job for printing using the SMB protocol .
*/
static int /* O - 0 = success, non-0 = failure */
smb_print ( struct cli_state * cli , /* I - SMB connection */
char * title , /* I - Title/job name */
FILE * fp ) /* I - File to print */
{
int fnum ; /* File number */
int nbytes , /* Number of bytes read */
tbytes ; /* Total bytes read */
2001-03-16 22:17:04 +03:00
char buffer [ 8192 ] , /* Buffer for copy */
* ptr ; /* Pointer into tile */
/*
* Sanitize the title . . .
*/
1999-12-17 04:48:16 +03:00
2001-03-16 22:17:04 +03:00
for ( ptr = title ; * ptr ; ptr + + )
2001-04-28 02:42:10 +04:00
if ( ! isalnum ( ( int ) * ptr ) & & ! isspace ( ( int ) * ptr ) )
2001-03-16 22:17:04 +03:00
* ptr = ' _ ' ;
1999-12-17 04:48:16 +03:00
/*
* Open the printer device . . .
*/
2000-01-08 13:15:53 +03:00
if ( ( fnum = cli_open ( cli , title , O_RDWR | O_CREAT | O_TRUNC , DENY_NONE ) ) = = - 1 )
1999-12-17 04:48:16 +03:00
{
2005-02-22 06:31:22 +03:00
fprintf ( stderr , " ERROR: %s opening remote spool %s \n " ,
1999-12-17 04:48:16 +03:00
cli_errstr ( cli ) , title ) ;
return ( 1 ) ;
}
/*
* Copy the file to the printer . . .
*/
if ( fp ! = stdin )
rewind ( fp ) ;
tbytes = 0 ;
while ( ( nbytes = fread ( buffer , 1 , sizeof ( buffer ) , fp ) ) > 0 )
{
if ( cli_write ( cli , fnum , 0 , buffer , tbytes , nbytes ) ! = nbytes )
{
2005-02-22 06:31:22 +03:00
fprintf ( stderr , " ERROR: Error writing spool: %s \n " , cli_errstr ( cli ) ) ;
1999-12-17 04:48:16 +03:00
break ;
}
tbytes + = nbytes ;
}
if ( ! cli_close ( cli , fnum ) )
{
2005-02-22 06:31:22 +03:00
fprintf ( stderr , " ERROR: %s closing remote spool %s \n " ,
1999-12-17 04:48:16 +03:00
cli_errstr ( cli ) , title ) ;
return ( 1 ) ;
}
else
return ( 0 ) ;
}
2007-06-16 22:54:13 +04:00
static char * uri_unescape_alloc ( const char * uritok )
{
2007-06-17 02:52:51 +04:00
char * ret ;
2007-06-16 22:54:13 +04:00
2007-06-17 02:52:51 +04:00
ret = ( char * ) SMB_STRDUP ( uritok ) ;
2007-06-16 22:54:13 +04:00
if ( ! ret ) return NULL ;
2007-06-17 02:52:51 +04:00
rfc1738_unescape ( ret ) ;
2007-06-16 22:54:13 +04:00
return ret ;
}