1
/***************************************************************************
2
smb4ksambaoptionshandler - This class handles the Samba options.
5
copyright : (C) 2006-2008 by Alexander Reinholdt
6
email : dustpuppy@users.berlios.de
7
***************************************************************************/
9
/***************************************************************************
10
* This program is free software; you can redistribute it and/or modify *
11
* it under the terms of the GNU General Public License as published by *
12
* the Free Software Foundation; either version 2 of the License, or *
13
* (at your option) any later version. *
15
* This program is distributed in the hope that it will be useful, but *
16
* WITHOUT ANY WARRANTY; without even the implied warranty of *
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
18
* General Public License for more details. *
20
* You should have received a copy of the GNU General Public License *
21
* along with this program; if not, write to the *
22
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
24
***************************************************************************/
28
#include <QTextStream>
31
#include <QXmlStreamReader>
32
#include <QXmlStreamWriter>
35
#include <kstandarddirs.h>
42
// system specific includes
44
#include <sys/types.h>
47
// application specific includes
48
#include <smb4ksambaoptionshandler.h>
49
#include <smb4kdefs.h>
50
#include <smb4kcoremessage.h>
51
#include <smb4kglobal.h>
52
#include <smb4ksambaoptionsinfo.h>
53
#include <smb4kshare.h>
54
#include <smb4ksettings.h>
55
#include <smb4kworkgroup.h>
56
#include <smb4khost.h>
58
using namespace Smb4KGlobal;
60
class Smb4KSambaOptionsHandlerPrivate
64
* The Smb4KSambaOptionsHandler instance
66
Smb4KSambaOptionsHandler instance;
70
K_GLOBAL_STATIC( Smb4KSambaOptionsHandlerPrivate, m_priv );
73
Smb4KSambaOptionsHandler::Smb4KSambaOptionsHandler()
76
// We need the directory.
77
QString dir = KGlobal::dirs()->locateLocal( "data", "smb4k", KGlobal::mainComponent() );
79
if ( !KGlobal::dirs()->exists( dir ) )
81
KGlobal::dirs()->makeDir( dir );
84
m_wins_server.clear();
90
Smb4KSambaOptionsHandler::~Smb4KSambaOptionsHandler()
92
while ( !m_list.isEmpty() )
94
delete m_list.takeFirst();
99
Smb4KSambaOptionsHandler *Smb4KSambaOptionsHandler::self()
101
return &m_priv->instance;
105
QList<Smb4KSambaOptionsInfo *> Smb4KSambaOptionsHandler::sharesToRemount()
107
QList<Smb4KSambaOptionsInfo *> remounts;
109
for ( int i = 0; i < m_list.size(); ++i )
111
if ( m_list.at( i )->remount() == Smb4KSambaOptionsInfo::DoRemount )
113
remounts.append( m_list.at( i ) );
127
void Smb4KSambaOptionsHandler::readCustomOptions()
129
// Check if an old custom_options file is present and load the options
130
// from there. Remove the file afterwards.
131
QFile file( KGlobal::dirs()->locateLocal( "data", "smb4k/custom_options", KGlobal::mainComponent() ) );
135
QStringList contents;
137
if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
139
QTextStream ts( &file );
140
// Note: With Qt 4.3 this seems to be obsolete, we'll keep
142
ts.setCodec( QTextCodec::codecForLocale() );
144
while ( !ts.atEnd() )
146
contents.append( ts.readLine( 0 ) );
155
Smb4KCoreMessage::error( ERROR_OPENING_FILE, file.fileName() );
161
if ( !contents.isEmpty() )
163
for ( int i = 0; i < contents.size(); ++i )
165
if ( contents.at( i ).startsWith( "[" ) )
167
Smb4KSambaOptionsInfo *info = new Smb4KSambaOptionsInfo();
168
info->setUNC( contents.at( i ).section( "[", 1, -1 ).section( "]", -2, 0 ) );
170
for ( int j = ++i; j < contents.size(); ++j )
172
if ( contents.at( j ).startsWith( "workgroup=" ) )
174
info->setWorkgroup( contents.at( j ).section( "=", 1, 1 ).trimmed() );
178
else if ( contents.at( j ).startsWith( "ip=" ) )
180
info->setIP( contents.at( j ).section( "=", 1, 1 ).trimmed() );
184
else if ( contents.at( j ).startsWith( "remount=" ) )
186
QString remount = contents.at( j ).section( "=", 1, 1 ).trimmed();
188
if ( QString::compare( remount, "true", Qt::CaseInsensitive ) == 0 )
190
info->setRemount( Smb4KSambaOptionsInfo::DoRemount );
192
else if ( QString::compare( remount, "true", Qt::CaseInsensitive ) == 0 )
194
info->setRemount( Smb4KSambaOptionsInfo::NoRemount );
198
info->setRemount( Smb4KSambaOptionsInfo::UndefinedRemount );
203
else if ( contents.at( j ).startsWith( "port=" ) )
205
int port = contents.at( j ).section( "=", 1, 1 ).trimmed().toInt();
207
info->setPort( port );
212
else if ( contents.at( j ).startsWith( "write access=" ) )
214
QString write_access = contents.at( j ).section( "=", 1, 1 ).trimmed();
216
if ( QString::compare( write_access, "true", Qt::CaseInsensitive ) == 0 )
218
info->setWriteAccess( Smb4KSambaOptionsInfo::ReadWrite );
220
else if ( QString::compare( write_access, "false", Qt::CaseInsensitive ) == 0 )
222
info->setWriteAccess( Smb4KSambaOptionsInfo::ReadOnly );
226
info->setWriteAccess( Smb4KSambaOptionsInfo::UndefinedWriteAccess );
232
else if ( contents.at( j ).startsWith( "protocol=" ) )
234
QString protocol = contents.at( j ).section( "=", 1, 1 ).trimmed();
236
if ( QString::compare( protocol, "auto" ) == 0 )
238
info->setProtocol( Smb4KSambaOptionsInfo::Automatic );
240
else if ( QString::compare( protocol, "rpc" ) == 0 )
242
info->setProtocol( Smb4KSambaOptionsInfo::RPC );
244
else if ( QString::compare( protocol, "rap" ) == 0 )
246
info->setProtocol( Smb4KSambaOptionsInfo::RAP );
248
else if ( QString::compare( protocol, "ads" ) == 0 )
250
info->setProtocol( Smb4KSambaOptionsInfo::ADS );
254
info->setProtocol( Smb4KSambaOptionsInfo::UndefinedProtocol );
259
else if ( contents.at( j ).startsWith( "kerberos=" ) )
261
QString use_kerberos = contents.at( j ).section( "=", 1, 1 ).trimmed();
263
if ( QString::compare( use_kerberos, "true", Qt::CaseInsensitive ) == 0 )
265
info->setUseKerberos( Smb4KSambaOptionsInfo::UseKerberos );
267
else if ( QString::compare( use_kerberos, "false", Qt::CaseInsensitive ) == 0 )
269
info->setUseKerberos( Smb4KSambaOptionsInfo::NoKerberos );
273
info->setUseKerberos( Smb4KSambaOptionsInfo::UndefinedKerberos );
278
else if ( contents.at( j ).startsWith( "uid=" ) )
280
info->setUID( (uid_t)contents.at( j ).section( "=", 1, 1 ).trimmed().toInt() );
284
else if ( contents.at( j ).startsWith( "gid=" ) )
286
info->setGID( (gid_t)contents.at( j ).section( "=", 1, 1 ).trimmed().toInt() );
290
else if ( contents.at( j ).isEmpty() || contents.at( j ).trimmed().startsWith( "[" ) )
302
has_custom_options( info );
304
m_list.append( info );
319
writeCustomOptions();
328
// Locate the XML file.
329
QFile xmlFile( KGlobal::dirs()->locateLocal( "data", "smb4k/custom_options.xml", KGlobal::mainComponent() ) );
331
if ( xmlFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
333
QXmlStreamReader xmlReader( &xmlFile );
335
while ( !xmlReader.atEnd() )
337
xmlReader.readNext();
339
if ( xmlReader.isStartElement() )
341
if ( xmlReader.name() == "custom_options" && xmlReader.attributes().value( "version" ) != "1.0" )
343
xmlReader.raiseError( i18n( "%1 is not a version 1.0 file." ).arg( xmlFile.fileName() ) );
349
if ( xmlReader.name() == "options" )
351
Smb4KSambaOptionsInfo *info = new Smb4KSambaOptionsInfo();
353
info->setProfile( xmlReader.attributes().value( "profile" ).toString() );
355
// The type attribute is not used at the moment.
357
while ( !(xmlReader.isEndElement() && xmlReader.name() == "options") )
359
xmlReader.readNext();
361
if ( xmlReader.isStartElement() )
363
if ( xmlReader.name() == "workgroup" )
365
info->setWorkgroup( xmlReader.readElementText() );
367
else if ( xmlReader.name() == "unc" )
369
info->setUNC( xmlReader.readElementText() );
371
else if ( xmlReader.name() == "ip" )
373
info->setIP( xmlReader.readElementText() );
375
else if ( xmlReader.name() == "custom" )
377
while ( !(xmlReader.isEndElement() && xmlReader.name() == "custom") )
379
xmlReader.readNext();
381
if ( xmlReader.isStartElement() )
383
if ( xmlReader.name() == "remount" )
385
QString remount = xmlReader.readElementText();
387
if ( QString::compare( remount, "true" ) == 0 )
389
info->setRemount( Smb4KSambaOptionsInfo::DoRemount );
391
else if ( QString::compare( remount, "false" ) == 0 )
393
info->setRemount( Smb4KSambaOptionsInfo::NoRemount );
397
info->setRemount( Smb4KSambaOptionsInfo::UndefinedRemount );
400
else if ( xmlReader.name() == "port" )
402
info->setPort( xmlReader.readElementText().toInt() );
404
else if ( xmlReader.name() == "protocol" )
406
QString protocol = xmlReader.readElementText();
408
if ( QString::compare( protocol, "auto" ) == 0 )
410
info->setProtocol( Smb4KSambaOptionsInfo::Automatic );
412
else if ( QString::compare( protocol, "rpc" ) == 0 )
414
info->setProtocol( Smb4KSambaOptionsInfo::RPC );
416
else if ( QString::compare( protocol, "rap" ) == 0 )
418
info->setProtocol( Smb4KSambaOptionsInfo::RAP );
420
else if ( QString::compare( protocol, "ads" ) == 0 )
422
info->setProtocol( Smb4KSambaOptionsInfo::ADS );
426
info->setProtocol( Smb4KSambaOptionsInfo::UndefinedProtocol );
430
else if ( xmlReader.name() == "write_access" )
432
QString write_access = xmlReader.readElementText();
434
if ( QString::compare( write_access, "true" ) == 0 )
436
info->setWriteAccess( Smb4KSambaOptionsInfo::ReadWrite );
438
else if ( QString::compare( write_access, "false" ) == 0 )
440
info->setWriteAccess( Smb4KSambaOptionsInfo::ReadOnly );
444
info->setWriteAccess( Smb4KSambaOptionsInfo::UndefinedWriteAccess );
448
else if ( xmlReader.name() == "kerberos" )
450
QString kerberos = xmlReader.readElementText();
452
if ( QString::compare( kerberos, "true" ) == 0 )
454
info->setUseKerberos( Smb4KSambaOptionsInfo::UseKerberos );
456
else if ( QString::compare( kerberos, "false" ) == 0 )
458
info->setUseKerberos( Smb4KSambaOptionsInfo::NoKerberos );
462
info->setUseKerberos( Smb4KSambaOptionsInfo::UndefinedKerberos );
465
else if ( xmlReader.name() == "uid" )
467
info->setUID( (uid_t)xmlReader.readElementText().toInt() );
469
else if ( xmlReader.name() == "gid" )
471
info->setGID( (gid_t)xmlReader.readElementText().toInt() );
497
m_list.append( info );
513
if ( xmlReader.hasError() )
515
Smb4KCoreMessage::error( ERROR_XML_ERROR, xmlFile.fileName(), xmlReader.errorString() );
524
if ( xmlFile.exists() )
526
Smb4KCoreMessage::error( ERROR_OPENING_FILE, xmlFile.fileName() );
538
void Smb4KSambaOptionsHandler::writeCustomOptions()
540
QFile xmlFile( KGlobal::dirs()->locateLocal( "data", "smb4k/custom_options.xml", KGlobal::mainComponent() ) );
542
if ( !m_list.isEmpty() )
544
if ( xmlFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
546
QXmlStreamWriter xmlWriter( &xmlFile );
547
#if QT_VERSION >= 0x040400
548
xmlWriter.setAutoFormatting( true );
551
xmlWriter.writeStartDocument();
552
xmlWriter.writeStartElement( "custom_options" );
553
xmlWriter.writeAttribute( "version", "1.0" );
555
for ( int i = 0; i < m_list.size(); ++i )
557
has_custom_options( m_list[i] );
559
if ( m_list.at( i )->hasCustomOptions() ||
560
m_list.at( i )->remount() == Smb4KSambaOptionsInfo::DoRemount )
562
xmlWriter.writeStartElement( "options" );
563
xmlWriter.writeAttribute( "type", m_list.at( i )->type() == Smb4KSambaOptionsInfo::Host ? "Host" : "Share" );
564
xmlWriter.writeAttribute( "profile", m_list.at( i )->profile() );
566
xmlWriter.writeTextElement( "workgroup", m_list.at( i )->workgroup() );
567
xmlWriter.writeTextElement( "unc", m_list.at( i )->unc() );
568
xmlWriter.writeTextElement( "ip", m_list.at( i )->ip() );
570
xmlWriter.writeStartElement( "custom" );
572
QMap<QString,QString> map = m_list.at( i )->entries();
573
QMapIterator<QString,QString> it( map );
575
while ( it.hasNext() )
579
if ( !it.value().isEmpty() )
581
xmlWriter.writeTextElement( it.key(), it.value() );
589
xmlWriter.writeEndElement();
590
xmlWriter.writeEndElement();
598
xmlWriter.writeEndDocument();
604
Smb4KCoreMessage::error( ERROR_OPENING_FILE, xmlFile.fileName() );
615
void Smb4KSambaOptionsHandler::remount( Smb4KShare *share, bool yes )
619
Smb4KSambaOptionsInfo *info = NULL;
621
if ( (info = find_item( share->unc() )) )
623
info->setRemount( yes ?
624
Smb4KSambaOptionsInfo::DoRemount :
625
Smb4KSambaOptionsInfo::NoRemount );
627
else if ( !info && yes )
629
info = new Smb4KSambaOptionsInfo( share );
630
info->setRemount( yes ?
631
Smb4KSambaOptionsInfo::DoRemount :
632
Smb4KSambaOptionsInfo::NoRemount );
634
m_list.append( info );
640
void Smb4KSambaOptionsHandler::sync()
642
writeCustomOptions();
646
Smb4KSambaOptionsInfo *Smb4KSambaOptionsHandler::find_item( const QString &item, bool exactMatch )
648
QString host = item.section( "/", 2, 2 ).trimmed();
650
Smb4KSambaOptionsInfo *info = NULL;
652
if ( !item.trimmed().isEmpty() )
654
for ( int i = 0; i < m_list.size(); ++i )
656
if ( QString::compare( item.toUpper(), m_list.at( i )->unc().toUpper() ) == 0 )
658
info = m_list.at( i );
662
else if ( QString::compare( host.toUpper(), m_list.at( i )->unc().toUpper() ) == 0 )
664
if ( !info && !exactMatch )
666
info = m_list.at( i );
682
const QString Smb4KSambaOptionsHandler::smbclientOptions( const Smb4KShare &share )
684
// FIXME: Make globalOptions() return a string.
686
// Get the global Samba options
687
(void) globalSambaOptions();
689
Smb4KSambaOptionsInfo *info = NULL;
691
if ( !share.isEmpty() )
693
info = find_item( share.name() );
698
// Get the strings that are needed to put the
699
// argument list together:
700
QString resolve_order = (!Smb4KSettings::nameResolveOrder().isEmpty() &&
701
QString::compare( Smb4KSettings::nameResolveOrder(),
702
m_samba_options["name resolve order"] ) != 0) ?
703
Smb4KSettings::nameResolveOrder() :
706
QString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
707
QString::compare( Smb4KSettings::netBIOSName(),
708
m_samba_options["netbios name"] ) != 0) ?
709
Smb4KSettings::netBIOSName() :
712
QString netbios_scope = (!Smb4KSettings::netBIOSScope().isEmpty() &&
713
QString::compare( Smb4KSettings::netBIOSScope(),
714
m_samba_options["netbios scope"] ) != 0) ?
715
Smb4KSettings::netBIOSScope() :
718
QString socket_options = (!Smb4KSettings::socketOptions().isEmpty() &&
719
QString::compare( Smb4KSettings::socketOptions(),
720
m_samba_options["socket options"] ) != 0) ?
721
Smb4KSettings::socketOptions() :
724
bool kerberos = false;
728
switch ( info->useKerberos() )
730
case Smb4KSambaOptionsInfo::UseKerberos:
736
case Smb4KSambaOptionsInfo::NoKerberos:
742
case Smb4KSambaOptionsInfo::UndefinedKerberos:
744
kerberos = Smb4KSettings::useKerberos();
756
kerberos = Smb4KSettings::useKerberos();
759
int port = info && info->port() != -1 ?
761
Smb4KSettings::remoteSMBPort();
763
// Options that are not customizable:
764
args.append( !resolve_order.isEmpty() ?
765
QString( " -R '%1'" ).arg( resolve_order ) :
768
args.append( !netbios_name.isEmpty() ?
769
QString( " -n '%1'" ).arg( netbios_name ) :
772
args.append( !netbios_scope.isEmpty() ?
773
QString( " -i '%1'" ).arg( netbios_scope ) :
776
args.append( !socket_options.isEmpty() ?
777
QString( " -O '%1'" ).arg( socket_options ) :
780
args.append( Smb4KSettings::bufferSize() != 65520 ?
781
QString( " -b %1" ).arg( Smb4KSettings::bufferSize() ) :
784
args.append( (Smb4KSettings::machineAccount() ?
788
switch ( Smb4KSettings::signingState() )
790
case Smb4KSettings::EnumSigningState::None:
792
// The user does not want this setting
796
case Smb4KSettings::EnumSigningState::On:
798
args.append( " -S on" );
802
case Smb4KSettings::EnumSigningState::Off:
804
args.append( " -S off" );
808
case Smb4KSettings::EnumSigningState::Required:
810
args.append( " -S required" );
820
args.append( (kerberos ?
824
args.append( QString( " -p %1" ).arg( port ) );
830
const QString Smb4KSambaOptionsHandler::nmblookupOptions( bool with_broadcast )
832
// Get the global Samba options
833
(void) globalSambaOptions();
837
QString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
838
QString::compare( Smb4KSettings::netBIOSName(),
839
m_samba_options["netbios name"] ) != 0) ?
840
Smb4KSettings::netBIOSName() :
843
QString netbios_scope = (!Smb4KSettings::netBIOSScope().isEmpty() &&
844
QString::compare( Smb4KSettings::netBIOSScope(),
845
m_samba_options["netbios scope"] ) != 0) ?
846
Smb4KSettings::netBIOSScope() :
849
QString socket_options = (!Smb4KSettings::socketOptions().isEmpty() &&
850
QString::compare( Smb4KSettings::socketOptions(),
851
m_samba_options["socket options"] ) != 0) ?
852
Smb4KSettings::socketOptions() :
855
QString domain = (!Smb4KSettings::domainName().isEmpty() &&
856
QString::compare( Smb4KSettings::domainName(),
857
m_samba_options["workgroup"] ) != 0) ?
858
Smb4KSettings::domainName() :
861
args.append( !netbios_name.isEmpty() ?
862
QString( " -n '%1'" ).arg( netbios_name ) :
865
args.append( !netbios_scope.isEmpty() ?
866
QString( " -i '%1'" ).arg( netbios_scope ) :
869
args.append( !socket_options.isEmpty() ?
870
QString( " -O '%1'" ).arg( socket_options ) :
873
args.append( !domain.isEmpty() ?
874
QString( " -W '%1'" ).arg( domain ) :
877
args.append( (!Smb4KSettings::broadcastAddress().isEmpty() &&
879
QString( " -B %1" ).arg( Smb4KSettings::broadcastAddress() ) :
882
args.append( Smb4KSettings::usePort137() ?
890
const QString Smb4KSambaOptionsHandler::netOptions( NetCommand command, const Smb4KHost &host )
892
// Find the host in the list.
893
Smb4KSambaOptionsInfo *info = find_item( host.name() );
895
// Determine the protocol that should be used.
896
QString protocol_hint;
898
if ( host.protocol() != Smb4KHost::Automatic )
900
// The protocol entry of the Smb4KHostItem overwrites
901
// the default protocol hint.
902
switch ( host.protocol() )
906
protocol_hint = "rpc";
912
protocol_hint = "rap";
918
protocol_hint = "ads";
930
switch ( Smb4KSettings::protocolHint() )
932
case Smb4KSettings::EnumProtocolHint::RPC:
934
protocol_hint = "rpc";
938
case Smb4KSettings::EnumProtocolHint::RAP:
940
protocol_hint = "rap";
944
case Smb4KSettings::EnumProtocolHint::ADS:
946
protocol_hint = "ads";
957
QString default_protocol;
961
switch ( info->protocol() )
963
case Smb4KSambaOptionsInfo::RPC:
965
default_protocol = "rpc";
969
case Smb4KSambaOptionsInfo::RAP:
971
default_protocol = "rap";
975
case Smb4KSambaOptionsInfo::ADS:
977
default_protocol = "ads";
983
default_protocol = protocol_hint;
989
default_protocol = protocol_hint;
992
QString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
993
QString::compare( Smb4KSettings::netBIOSName(),
994
m_samba_options["netbios name"] ) != 0) ?
995
Smb4KSettings::netBIOSName() :
998
QString domain = (!Smb4KSettings::domainName().isEmpty() &&
999
QString::compare( Smb4KSettings::domainName(),
1000
m_samba_options["workgroup"] ) != 0) ?
1001
Smb4KSettings::domainName() :
1004
int port = (info && info->port() != -1) ?
1006
Smb4KSettings::remoteSMBPort();
1015
// We can only use "rpc" and "rap" protocol hints here. The others
1017
// Note: The protocol entry of the Smb4KHost object will always
1018
// overwrite the default protocol.
1019
switch ( host.protocol() )
1021
case Smb4KHost::RPC:
1023
args.append( " "+protocol_hint+" share list -l" );
1026
case Smb4KHost::RAP:
1028
// protocol_hint carries the correct protocol:
1029
args.append( " "+protocol_hint+" share -l" );
1034
if ( !default_protocol.isEmpty() )
1036
if ( QString::compare( default_protocol, "rpc", Qt::CaseInsensitive ) == 0 )
1038
args.append( " "+default_protocol+" share list -l" );
1040
else if ( QString::compare( default_protocol, "rap", Qt::CaseInsensitive ) == 0 )
1042
args.append( " "+default_protocol+" share -l" );
1046
// Automatic detection
1047
args.append( " share list -l" );
1052
// Automatic detection
1053
args.append( " share list -l" );
1064
// Check that the server name is present:
1065
if ( host.name().trimmed().isEmpty() )
1067
Smb4KCoreMessage::error( ERROR_NET_COMMAND );
1069
return args; // still empty
1072
// This lookup command takes no protocol:
1073
args.append( QString( " lookup host %1" ).arg( KShell::quoteArg( host.name() ) ) );
1079
// Check that the domain name is present:
1080
if ( host.workgroup().trimmed().isEmpty() )
1082
Smb4KCoreMessage::error( ERROR_NET_COMMAND );
1084
return args; // still empty
1087
// This lookup command takes no protocol:
1088
args.append( QString( " lookup master %1" ).arg( KShell::quoteArg( host.workgroup() ) ) );
1094
// Bypass the rest and return an empty string.
1099
args.append( !domain.isEmpty() ?
1100
QString( " -W %1" ).arg( KShell::quoteArg( domain ) ) :
1103
args.append( !netbios_name.isEmpty() ?
1104
QString( " -n %1" ).arg( KShell::quoteArg( netbios_name ) ) :
1107
args.append( Smb4KSettings::machineAccount() ?
1111
args.append( QString( " -p %1" ).arg( port ) );
1117
const QString Smb4KSambaOptionsHandler::netOptions( NetCommand command, const Smb4KWorkgroup &workgroup )
1119
// Find the host in the list.
1120
Smb4KSambaOptionsInfo *info = find_item( workgroup.masterBrowserName() );
1122
QString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
1123
QString::compare( Smb4KSettings::netBIOSName(),
1124
m_samba_options["netbios name"] ) != 0) ?
1125
Smb4KSettings::netBIOSName() :
1128
QString domain = (!Smb4KSettings::domainName().isEmpty() &&
1129
QString::compare( Smb4KSettings::domainName(),
1130
m_samba_options["workgroup"] ) != 0) ?
1131
Smb4KSettings::domainName() :
1134
int port = (info && info->port() != -1) ?
1136
Smb4KSettings::remoteSMBPort();
1144
// Check that the server name is present:
1145
if ( workgroup.masterBrowserName().trimmed().isEmpty() )
1147
Smb4KCoreMessage::error( ERROR_NET_COMMAND );
1149
return args; // still empty
1152
// This lookup command takes no protocol:
1153
args.append( QString( " lookup host %1" )
1154
.arg( KShell::quoteArg( workgroup.masterBrowserName() ) ) );
1160
// Check that the domain name is present:
1161
if ( workgroup.name().trimmed().isEmpty() )
1163
Smb4KCoreMessage::error( ERROR_NET_COMMAND );
1165
return args; // still empty
1168
// This lookup command takes no protocol:
1169
args.append( QString( " lookup master %1" ).arg( KShell::quoteArg( workgroup.name() ) ) );
1175
// Bypass the rest and return an empty string.
1180
args.append( !domain.isEmpty() ?
1181
QString( " -W %1" ).arg( KShell::quoteArg( domain ) ) :
1184
args.append( !netbios_name.isEmpty() ?
1185
QString( " -n %1" ).arg( KShell::quoteArg( netbios_name ) ) :
1188
args.append( Smb4KSettings::machineAccount() ?
1192
args.append( QString( " -p %1" ).arg( port ) );
1198
const QString Smb4KSambaOptionsHandler::netOptions( NetCommand command )
1200
QString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
1201
QString::compare( Smb4KSettings::netBIOSName(),
1202
m_samba_options["netbios name"] ) != 0) ?
1203
Smb4KSettings::netBIOSName() :
1206
QString domain = (!Smb4KSettings::domainName().isEmpty() &&
1207
QString::compare( Smb4KSettings::domainName(),
1208
m_samba_options["workgroup"] ) != 0) ?
1209
Smb4KSettings::domainName() :
1218
// This only works with the rap protocol:
1219
args.append( " rap server domain" );
1225
// This only works with the rap protocol:
1226
args.append( " rap domain" );
1232
// Bypass the rest and return an
1238
args.append( !domain.isEmpty() ?
1239
QString( " -W %1" ).arg( KShell::quoteArg( domain ) ) :
1242
args.append( !netbios_name.isEmpty() ?
1243
QString( " -n %1" ).arg( KShell::quoteArg( netbios_name ) ) :
1246
args.append( Smb4KSettings::machineAccount() ?
1250
args.append( QString( " -p %1" ).arg( Smb4KSettings::remoteSMBPort() ) );
1256
const QString Smb4KSambaOptionsHandler::mountOptions( const QString &share )
1258
Smb4KSambaOptionsInfo *info = find_item( share );
1261
// Read the global Samba options from smb.conf:
1262
(void) globalSambaOptions();
1264
// Get the strings needed to put the argument list together:
1265
uid_t uid = info ? info->uid() : (uid_t)Smb4KSettings::userID().toInt();
1266
gid_t gid = info ? info->gid() : (gid_t)Smb4KSettings::groupID().toInt();
1268
QString charset, codepage;
1270
switch ( Smb4KSettings::clientCharset() )
1272
case Smb4KSettings::EnumClientCharset::default_charset:
1274
charset = m_samba_options["unix charset"].toLower(); // maybe empty
1278
case Smb4KSettings::EnumClientCharset::iso8859_1:
1280
charset = "iso8859-1";
1284
case Smb4KSettings::EnumClientCharset::iso8859_2:
1286
charset = "iso8859-2";
1290
case Smb4KSettings::EnumClientCharset::iso8859_3:
1292
charset = "iso8859-3";
1296
case Smb4KSettings::EnumClientCharset::iso8859_4:
1298
charset = "iso8859-4";
1302
case Smb4KSettings::EnumClientCharset::iso8859_5:
1304
charset = "iso8859-5";
1308
case Smb4KSettings::EnumClientCharset::iso8859_6:
1310
charset = "iso8859-6";
1314
case Smb4KSettings::EnumClientCharset::iso8859_7:
1316
charset = "iso8859-7";
1320
case Smb4KSettings::EnumClientCharset::iso8859_8:
1322
charset = "iso8859-8";
1326
case Smb4KSettings::EnumClientCharset::iso8859_9:
1328
charset = "iso8859-9";
1332
case Smb4KSettings::EnumClientCharset::iso8859_13:
1334
charset = "iso8859-13";
1338
case Smb4KSettings::EnumClientCharset::iso8859_14:
1340
charset = "iso8859-14";
1344
case Smb4KSettings::EnumClientCharset::iso8859_15:
1346
charset = "iso8859-15";
1350
case Smb4KSettings::EnumClientCharset::utf8:
1356
case Smb4KSettings::EnumClientCharset::koi8_r:
1362
case Smb4KSettings::EnumClientCharset::koi8_u:
1368
case Smb4KSettings::EnumClientCharset::koi8_ru:
1370
charset = "koi8-ru";
1374
case Smb4KSettings::EnumClientCharset::cp1251:
1380
case Smb4KSettings::EnumClientCharset::gb2312:
1386
case Smb4KSettings::EnumClientCharset::big5:
1392
case Smb4KSettings::EnumClientCharset::euc_jp:
1398
case Smb4KSettings::EnumClientCharset::euc_kr:
1404
case Smb4KSettings::EnumClientCharset::tis_620:
1406
charset = "tis-620";
1418
QString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
1419
QString::compare( Smb4KSettings::netBIOSName(),
1420
m_samba_options["netbios name"] ) != 0) ?
1421
Smb4KSettings::netBIOSName() :
1424
QString socket_options = (!Smb4KSettings::socketOptions().isEmpty() &&
1425
QString::compare( Smb4KSettings::socketOptions(),
1426
m_samba_options["socket options"] ) != 0) ?
1427
Smb4KSettings::socketOptions() :
1430
QString netbios_scope = (!Smb4KSettings::netBIOSScope().isEmpty() &&
1431
QString::compare( Smb4KSettings::netBIOSScope(),
1432
m_samba_options["netbios scope"] ) != 0) ?
1433
Smb4KSettings::netBIOSScope() :
1436
int port = info && info->port() != -1 ?
1438
Smb4KSettings::remoteFileSystemPort();
1440
bool kerberos = false;
1444
switch ( info->useKerberos() )
1446
case Smb4KSambaOptionsInfo::UseKerberos:
1452
case Smb4KSambaOptionsInfo::NoKerberos:
1458
case Smb4KSambaOptionsInfo::UndefinedKerberos:
1460
kerberos = Smb4KSettings::useKerberos();
1472
kerberos = Smb4KSettings::useKerberos();
1475
bool write_access = true;
1479
switch ( info->writeAccess() )
1481
case Smb4KSambaOptionsInfo::ReadWrite:
1483
write_access = true;
1487
case Smb4KSambaOptionsInfo::ReadOnly:
1489
write_access = false;
1493
case Smb4KSambaOptionsInfo::UndefinedWriteAccess:
1495
write_access = (Smb4KSettings::writeAccess() == Smb4KSettings::EnumWriteAccess::ReadWrite);
1507
write_access = (Smb4KSettings::writeAccess() == Smb4KSettings::EnumWriteAccess::ReadWrite);
1510
// Compile the arguments list:
1511
args.append( !netbios_name.isEmpty() ?
1512
QString( "netbiosname='%1'," ).arg( netbios_name ) :
1515
args.append( QString( "uid=%1," ).arg( uid ) );
1517
args.append( QString( "gid=%1," ).arg( gid ) );
1519
args.append( QString( "port=%1," ).arg( port ) );
1521
args.append( !charset.isEmpty() ?
1522
QString( "iocharset=%1," ).arg( charset ) :
1525
args.append( write_access ? "rw," : "ro," );
1527
args.append( !Smb4KSettings::fileMask().isEmpty() ?
1528
QString( "file_mode=%1," ).arg( Smb4KSettings::fileMask() ) :
1531
args.append( !Smb4KSettings::directoryMask().isEmpty() ?
1532
QString( "dir_mode=%1," ).arg( Smb4KSettings::directoryMask() ) :
1535
args.append( Smb4KSettings::permissionChecks() ?
1539
args.append( Smb4KSettings::clientControlsIDs() ?
1543
args.append( Smb4KSettings::serverInodeNumbers() ?
1547
args.append( Smb4KSettings::inodeDataCaching() ?
1551
args.append( Smb4KSettings::translateReservedChars() ?
1555
args.append( Smb4KSettings::noLocking() ?
1559
args.append( !Smb4KSettings::customCIFSOptions().isEmpty() ?
1560
Smb4KSettings::customCIFSOptions() :
1563
args.append( !args.endsWith( "," ) ? "," : "" );
1567
// Compile the arguments list:
1568
args.append( QString( " -u %1" ).arg( uid ) );
1570
args.append( QString( " -g %1" ).arg( gid ) );
1572
args.append( !charset.isEmpty() && !codepage.isEmpty() ?
1573
QString( " -E %1:%2" ).arg( charset, codepage ) :
1576
args.append( !Smb4KSettings::fileMask().isEmpty() ?
1577
QString( " -f %1" ).arg( Smb4KSettings::fileMask() ) :
1580
args.append( !Smb4KSettings::directoryMask().isEmpty() ?
1581
QString( " -d %1" ).arg( Smb4KSettings::directoryMask() ) :
1584
// NOTE: Under FreeBSD the port must be managed by the mounter.
1586
// FIXME: If the manual page was of more use, we could probably implement
1587
// more of the arguments that are available for mount_smbfs.
1595
void Smb4KSambaOptionsHandler::read_smb_conf()
1597
// Clear the options list before reading.
1598
m_samba_options.clear();
1602
paths << "/etc/samba";
1603
paths << "/usr/local/etc";
1604
paths << "/usr/local/etc/samba";
1606
QFile file( "smb.conf" );
1608
QStringList contents;
1610
// Locate the file and read its contents:
1611
for ( int i = 0; i < paths.size(); ++i )
1613
QDir::setCurrent( paths.at( i ) );
1615
if ( file.exists() )
1617
if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
1619
QTextStream ts( &file );
1620
// Note: With Qt 4.3 this seems to be obsolete, we'll keep
1622
ts.setCodec( QTextCodec::codecForLocale() );
1624
while ( !ts.atEnd() )
1626
contents.append( ts.readLine( 0 ) );
1633
Smb4KCoreMessage::error( ERROR_OPENING_FILE, paths.at( i )+QDir::separator()+file.fileName() );
1647
if ( !contents.isEmpty() )
1649
// Process the file contents.
1650
for ( int i = contents.indexOf( "[global]", 0 ); i < contents.size(); ++i )
1652
if ( contents.at( i ).trimmed().startsWith( "#" ) ||
1653
contents.at( i ).trimmed().startsWith( ";" ) )
1655
// This is a comment. We do not need it.
1658
else if ( contents.at( i ).trimmed().startsWith( "include" ) )
1660
// Look for the include file and put its contents into the
1661
// m_samba_options map.
1662
file.setFileName( contents.at( i ).section( "=", 1, 1 ).trimmed() );
1664
if ( file.exists() )
1666
if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
1668
QTextStream ts( &file );
1669
// Note: With Qt 4.3 this seems to be obsolete, we'll keep
1671
ts.setCodec( QTextCodec::codecForLocale() );
1675
while( !ts.atEnd() )
1677
buffer = ts.readLine( 0 ).trimmed();
1679
if ( buffer.startsWith( "#" ) || buffer.startsWith( ";" ) )
1685
QString key = buffer.section( "=", 0, 0 ).trimmed().toLower();
1686
m_samba_options[key] = buffer.section( "=", 1, 1 ).trimmed().toUpper();
1694
Smb4KCoreMessage::error( ERROR_OPENING_FILE, file.fileName() );
1696
// Continue reading the smb.conf file.
1701
else if ( contents.at( i ).startsWith( "[" ) &&
1702
!contents.at( i ).contains( "[global]", Qt::CaseSensitive ) )
1704
// We reached the end of the [global] section. Stop here.
1709
// Put the entries of the [global] section into the m_samba_options
1711
QString key = contents.at( i ).section( "=", 0, 0 ).trimmed().toLower();
1712
m_samba_options[key] = contents.at( i ).section( "=", 1, 1 ).trimmed().toUpper();
1721
// Post-processing. Some values should be entered with their defaults, if they are
1722
// not already present.
1723
if ( !m_samba_options.contains( "netbios name" ) )
1725
size_t hostnamelen = 255;
1726
char *hostname = new char[hostnamelen];
1728
if ( gethostname( hostname, hostnamelen ) == -1 )
1731
Smb4KCoreMessage::error( ERROR_GETTING_HOSTNAME, QString(), strerror( error ) );
1735
m_samba_options["netbios name"] = ( QString( "%1" ).arg( hostname ) ).toUpper();
1743
const QMap<QString,QString> &Smb4KSambaOptionsHandler::globalSambaOptions()
1745
if ( m_samba_options.isEmpty() )
1750
return m_samba_options;
1754
const QString &Smb4KSambaOptionsHandler::winsServer()
1756
if ( m_wins_server.isEmpty() )
1758
(void) globalSambaOptions();
1760
if ( !m_samba_options["wins server"].isEmpty() )
1762
m_wins_server = m_samba_options["wins server"];
1764
else if ( !m_samba_options["wins support"].isEmpty() &&
1765
(QString::compare( m_samba_options["wins support"], "yes", Qt::CaseInsensitive ) == 0 ||
1766
QString::compare( m_samba_options["wins support"], "true", Qt::CaseInsensitive ) == 0) )
1768
m_wins_server = "127.0.0.1";
1772
return m_wins_server;
1776
void Smb4KSambaOptionsHandler::addItem( Smb4KSambaOptionsInfo *info, bool s )
1778
has_custom_options( info );
1780
if ( info->hasCustomOptions() ||
1781
info->remount() == Smb4KSambaOptionsInfo::DoRemount )
1783
Smb4KSambaOptionsInfo *item = find_item( info->unc() );
1785
if ( item && QString::compare( item->unc(), info->unc(), Qt::CaseInsensitive ) == 0 )
1787
item->update( info );
1791
m_list.append( info );
1801
removeItem( info->unc(), false );
1806
void Smb4KSambaOptionsHandler::removeItem( const QString &unc, bool s )
1808
Smb4KSambaOptionsInfo *item = find_item( unc );
1810
if ( item && QString::compare( item->unc(), unc, Qt::CaseInsensitive ) == 0 )
1812
int index = m_list.indexOf( item, 0 );
1813
delete m_list.takeAt( index );
1823
const QString Smb4KSambaOptionsHandler::smbtreeOptions( const QString &master )
1825
Smb4KSambaOptionsInfo *info = NULL;
1827
if ( !master.isEmpty() )
1829
info = find_item( master );
1832
bool kerberos = false;
1836
switch ( info->useKerberos() )
1838
case Smb4KSambaOptionsInfo::UseKerberos:
1844
case Smb4KSambaOptionsInfo::NoKerberos:
1850
case Smb4KSambaOptionsInfo::UndefinedKerberos:
1852
kerberos = Smb4KSettings::useKerberos();
1864
kerberos = Smb4KSettings::useKerberos();
1869
args.append( (Smb4KSettings::machineAccount() ?
1873
switch ( Smb4KSettings::signingState() )
1875
case Smb4KSettings::EnumSigningState::None:
1877
// The user does not want this setting
1881
case Smb4KSettings::EnumSigningState::On:
1883
args.append( " -S on" );
1887
case Smb4KSettings::EnumSigningState::Off:
1889
args.append( " -S off" );
1893
case Smb4KSettings::EnumSigningState::Required:
1895
args.append( " -S required" );
1905
args.append( (Smb4KSettings::smbtreeSendBroadcasts() ?
1909
args.append( (kerberos ?
1917
void Smb4KSambaOptionsHandler::updateCustomOptions( const QList<Smb4KSambaOptionsInfo *> &list )
1919
if ( !list.isEmpty() )
1921
// Delete obsolete items.
1922
for ( int i = 0; i < m_list.size(); ++i )
1926
for ( int j = 0; j < list.size(); ++j )
1928
if ( QString::compare( m_list.at( i )->unc(), list.at( j )->unc(), Qt::CaseInsensitive ) == 0 )
1942
delete m_list.takeAt( i );
1952
// Update and add items.
1953
for ( int i = 0; i < list.size(); ++i )
1955
Smb4KSambaOptionsInfo *info = find_item( list.at( i )->unc() );
1959
info->update( list.at( i ) );
1965
m_list.append( list.at( i ) );
1973
while ( !m_list.isEmpty() )
1975
delete m_list.takeFirst();
1983
void Smb4KSambaOptionsHandler::has_custom_options( Smb4KSambaOptionsInfo *item )
1987
switch ( item->type() )
1989
case Smb4KSambaOptionsInfo::Host:
1991
Smb4KSambaOptionsInfo::Protocol protocol_hint;
1993
switch ( Smb4KSettings::protocolHint() )
1995
case Smb4KSettings::EnumProtocolHint::Automatic:
1997
protocol_hint = Smb4KSambaOptionsInfo::Automatic;
2001
case Smb4KSettings::EnumProtocolHint::RPC:
2003
protocol_hint = Smb4KSambaOptionsInfo::RPC;
2007
case Smb4KSettings::EnumProtocolHint::RAP:
2009
protocol_hint = Smb4KSambaOptionsInfo::RAP;
2013
case Smb4KSettings::EnumProtocolHint::ADS:
2015
protocol_hint = Smb4KSambaOptionsInfo::ADS;
2021
protocol_hint = Smb4KSambaOptionsInfo::UndefinedProtocol;
2027
Smb4KSambaOptionsInfo::Kerberos default_kerberos = Smb4KSambaOptionsInfo::UndefinedKerberos;
2029
if ( Smb4KSettings::useKerberos() )
2031
default_kerberos = Smb4KSambaOptionsInfo::UseKerberos;
2035
default_kerberos = Smb4KSambaOptionsInfo::NoKerberos;
2038
if ( item->protocol() != Smb4KSambaOptionsInfo::UndefinedProtocol &&
2039
item->protocol() != protocol_hint )
2041
item->setHasCustomOptions( true );
2045
else if ( item->port() != -1 &&
2046
item->port() != Smb4KSettings::remoteSMBPort() )
2048
item->setHasCustomOptions( true );
2052
else if ( item->useKerberos() != Smb4KSambaOptionsInfo::UndefinedKerberos &&
2053
item->useKerberos() != default_kerberos )
2055
item->setHasCustomOptions( true );
2066
case Smb4KSambaOptionsInfo::Share:
2069
Smb4KSambaOptionsInfo::WriteAccess write_access;
2071
switch( Smb4KSettings::writeAccess() )
2073
case Smb4KSettings::EnumWriteAccess::ReadWrite:
2075
write_access = Smb4KSambaOptionsInfo::ReadWrite;
2079
case Smb4KSettings::EnumWriteAccess::ReadOnly:
2081
write_access = Smb4KSambaOptionsInfo::ReadOnly;
2087
write_access = Smb4KSambaOptionsInfo::UndefinedWriteAccess;
2094
Smb4KSambaOptionsInfo::Kerberos default_kerberos = Smb4KSambaOptionsInfo::UndefinedKerberos;
2096
if ( Smb4KSettings::useKerberos() )
2098
default_kerberos = Smb4KSambaOptionsInfo::UseKerberos;
2102
default_kerberos = Smb4KSambaOptionsInfo::NoKerberos;
2106
if ( item->port() != -1 &&
2107
item->port() != Smb4KSettings::remoteFileSystemPort() )
2109
item->setHasCustomOptions( true );
2113
else if ( item->writeAccess() != Smb4KSambaOptionsInfo::UndefinedWriteAccess &&
2114
item->writeAccess() != write_access )
2116
item->setHasCustomOptions( true );
2120
else if ( item->useKerberos() != Smb4KSambaOptionsInfo::UndefinedKerberos &&
2121
item->useKerberos() != default_kerberos )
2123
item->setHasCustomOptions( true );
2128
if ( item->port() != -1 &&
2129
item->port() != Smb4KSettings::remoteSMBPort() )
2131
item->setHasCustomOptions( true );
2136
else if ( item->uidIsSet() && (item->uid() != (uid_t)Smb4KSettings::userID().toInt()) )
2138
item->setHasCustomOptions( true );
2142
else if ( item->gidIsSet() && (item->gid() != (gid_t)Smb4KSettings::groupID().toInt()) )
2144
item->setHasCustomOptions( true );
2168
#include "smb4ksambaoptionshandler.moc"