Smb4K – Samba (SMB) share advanced browser
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1560 lines
39KB

  1. /***************************************************************************
  2. smb4ksambaoptionshandler - This class handles the Samba options.
  3. -------------------
  4. begin : So Mai 14 2006
  5. copyright : (C) 2006-2007 by Alexander Reinholdt
  6. email : dustpuppy@users.berlios.de
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. * This program is distributed in the hope that it will be useful, but *
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  17. * General Public License for more details. *
  18. * *
  19. * You should have received a copy of the GNU General Public License *
  20. * along with this program; if not, write to the *
  21. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
  22. * MA 02110-1301 USA *
  23. ***************************************************************************/
  24. // TQt includes
  25. #include <tqfile.h>
  26. #include <tqtextstream.h>
  27. #include <tqdir.h>
  28. // KDE includes
  29. #include <kstandarddirs.h>
  30. #include <kprocess.h>
  31. #include <kdebug.h>
  32. #include <klocale.h>
  33. // system specific includes
  34. #include <unistd.h>
  35. #include <sys/types.h>
  36. #include <errno.h>
  37. // application specific includes
  38. #include "smb4ksambaoptionshandler.h"
  39. #include "smb4kdefs.h"
  40. #include "smb4kerror.h"
  41. #include "smb4kglobal.h"
  42. #include "smb4ksambaoptionsinfo.h"
  43. #include "smb4kshare.h"
  44. #include "smb4ksettings.h"
  45. using namespace Smb4KGlobal;
  46. Smb4KSambaOptionsHandler::Smb4KSambaOptionsHandler( TQObject *parent, const char *name )
  47. : TQObject( parent, name )
  48. {
  49. // We need the directory.
  50. KStandardDirs *stddir = new KStandardDirs();
  51. TQString dir = locateLocal( "data", "smb4k", KGlobal::instance() );
  52. if ( !stddir->exists( dir ) )
  53. {
  54. stddir->makeDir( dir );
  55. }
  56. delete stddir;
  57. m_wins_server = TQString();
  58. }
  59. Smb4KSambaOptionsHandler::~Smb4KSambaOptionsHandler()
  60. {
  61. for ( TQValueList<Smb4KSambaOptionsInfo *>::Iterator it = m_list.begin();
  62. it != m_list.end(); ++it )
  63. {
  64. delete *it;
  65. }
  66. m_list.clear();
  67. }
  68. const TQValueList<Smb4KSambaOptionsInfo *> &Smb4KSambaOptionsHandler::customOptionsList()
  69. {
  70. if ( m_list.isEmpty() )
  71. {
  72. read_options();
  73. }
  74. return m_list;
  75. }
  76. void Smb4KSambaOptionsHandler::read_options()
  77. {
  78. // Clear the list before filling it (again)
  79. if ( !m_list.isEmpty() )
  80. {
  81. for ( TQValueList<Smb4KSambaOptionsInfo *>::Iterator it = m_list.begin();
  82. it != m_list.end(); ++it )
  83. {
  84. delete *it;
  85. }
  86. m_list.clear();
  87. }
  88. TQFile file( locateLocal( "data", "smb4k/custom_options", KGlobal::instance() ) );
  89. TQStringList contents;
  90. if ( file.open( IO_ReadOnly ) )
  91. {
  92. TQTextStream ts( &file );
  93. ts.setEncoding( TQTextStream::Locale );
  94. contents = TQStringList::split( '\n', ts.read(), true );
  95. file.close();
  96. }
  97. else
  98. {
  99. if ( file.exists() )
  100. {
  101. Smb4KError::error( ERROR_READING_FILE, file.name() );
  102. }
  103. return;
  104. }
  105. if ( !contents.isEmpty() )
  106. {
  107. for ( TQStringList::ConstIterator it = contents.begin(); it != contents.end(); ++it )
  108. {
  109. if ( (*it).startsWith( "[" ) )
  110. {
  111. Smb4KSambaOptionsInfo *info = new Smb4KSambaOptionsInfo( (*it).section( "[", 1, -1 ).section( "]", -2, 0 ) );
  112. for ( TQStringList::ConstIterator i = ++it; i != contents.end(); ++i )
  113. {
  114. if ( (*i).startsWith( "remount=" ) )
  115. {
  116. bool remount = TQString::compare( (*i).section( "=", 1, 1 ).stripWhiteSpace(), "true" ) == 0 ? true : false;
  117. info->setRemount( remount );
  118. continue;
  119. }
  120. else if ( (*i).startsWith( "port=" ) )
  121. {
  122. int port = (*i).section( "=", 1, 1 ).stripWhiteSpace().toInt();
  123. info->setPort( port );
  124. continue;
  125. }
  126. #ifndef __FreeBSD__
  127. else if ( (*i).startsWith( "filesystem=" ) )
  128. {
  129. info->setFilesystem( (*i).section( "=", 1, 1 ).stripWhiteSpace() );
  130. continue;
  131. }
  132. else if ( (*i).startsWith( "read-write=" ) ) // Deprecated since version 0.9.0
  133. {
  134. info->setWriteAccess( TQString::compare( (*i).section( "=", 1, 1 ).stripWhiteSpace(), "true" ) == 0 );
  135. continue;
  136. }
  137. else if ( (*i).startsWith( "write access=" ) )
  138. {
  139. info->setWriteAccess( TQString::compare( (*i).section( "=", 1, 1 ).stripWhiteSpace(), "true" ) == 0 );
  140. continue;
  141. }
  142. #endif
  143. else if ( (*i).startsWith( "protocol=" ) )
  144. {
  145. info->setProtocol( (*i).section( "=", 1, 1 ).stripWhiteSpace() );
  146. continue;
  147. }
  148. else if ( (*i).startsWith( "kerberos=" ) )
  149. {
  150. info->setKerberos( TQString::compare( (*i).section( "=", 1, 1 ).stripWhiteSpace(), "true" ) == 0 );
  151. continue;
  152. }
  153. else if ( (*i).startsWith( "uid=" ) )
  154. {
  155. info->setUID( (*i).section( "=", 1, 1 ).stripWhiteSpace() );
  156. continue;
  157. }
  158. else if ( (*i).startsWith( "gid=" ) )
  159. {
  160. info->setGID( (*i).section( "=", 1, 1 ).stripWhiteSpace() );
  161. continue;
  162. }
  163. else if ( (*i).isEmpty() || (*i).stripWhiteSpace().startsWith( "[" ) )
  164. {
  165. it = i;
  166. break;
  167. }
  168. else
  169. {
  170. continue;
  171. }
  172. }
  173. m_list.append( info );
  174. }
  175. else
  176. {
  177. continue;
  178. }
  179. }
  180. }
  181. }
  182. void Smb4KSambaOptionsHandler::write_options()
  183. {
  184. TQString protocol_hint;
  185. // Determine the protocol hint specified by the user:
  186. switch ( Smb4KSettings::protocolHint() )
  187. {
  188. case Smb4KSettings::EnumProtocolHint::Automatic:
  189. {
  190. // In this case the user leaves it to the net
  191. // command to determine the right protocol.
  192. protocol_hint = TQString();
  193. break;
  194. }
  195. case Smb4KSettings::EnumProtocolHint::RPC:
  196. {
  197. protocol_hint = "rpc";
  198. break;
  199. }
  200. case Smb4KSettings::EnumProtocolHint::RAP:
  201. {
  202. protocol_hint = "rap";
  203. break;
  204. }
  205. case Smb4KSettings::EnumProtocolHint::ADS:
  206. {
  207. protocol_hint = "ads";
  208. break;
  209. }
  210. default:
  211. {
  212. protocol_hint = TQString();
  213. break;
  214. }
  215. }
  216. #ifndef __FreeBSD__
  217. TQString default_filesystem;
  218. switch( Smb4KSettings::filesystem() )
  219. {
  220. case Smb4KSettings::EnumFilesystem::CIFS:
  221. {
  222. default_filesystem = "cifs";
  223. break;
  224. }
  225. case Smb4KSettings::EnumFilesystem::SMBFS:
  226. {
  227. default_filesystem = "smbfs";
  228. break;
  229. }
  230. default:
  231. {
  232. // FIXME: Set default_filesystem to "cifs"?
  233. break;
  234. }
  235. }
  236. bool write_access = true;
  237. switch( Smb4KSettings::writeAccess() )
  238. {
  239. case Smb4KSettings::EnumWriteAccess::ReadWrite:
  240. {
  241. write_access = true;
  242. break;
  243. }
  244. case Smb4KSettings::EnumWriteAccess::ReadOnly:
  245. {
  246. write_access = false;
  247. break;
  248. }
  249. default:
  250. {
  251. break;
  252. }
  253. }
  254. #endif
  255. TQFile file( locateLocal( "data", "smb4k/custom_options", KGlobal::instance() ) );
  256. if ( !m_list.isEmpty() )
  257. {
  258. if ( file.open( IO_WriteOnly ) )
  259. {
  260. TQTextStream ts( &file );
  261. ts.setEncoding( TQTextStream::Locale );
  262. for ( TQValueList<Smb4KSambaOptionsInfo *>::ConstIterator it = m_list.begin(); it != m_list.end(); ++it )
  263. {
  264. switch ( (*it)->type() )
  265. {
  266. case Smb4KSambaOptionsInfo::Host:
  267. {
  268. // Check if we need to write anything:
  269. if ( (*it)->port() != -1 ||
  270. !(*it)->protocol().stripWhiteSpace().isEmpty() ||
  271. ((*it)->kerberos() != Smb4KSettings::useKerberos()) )
  272. {
  273. ts << "[" << (*it)->itemName() << "]" << endl;
  274. ts << "port=" << ((*it)->port() != -1 ? (*it)->port() :
  275. Smb4KSettings::remotePort()) << endl;
  276. ts << "kerberos=" << ((*it)->kerberos() ? "true" : "false") << endl;
  277. ts << "protocol=" << (!(*it)->protocol().stripWhiteSpace().isEmpty() ?
  278. (*it)->protocol() : protocol_hint) << endl;
  279. }
  280. else
  281. {
  282. // Do nothing
  283. }
  284. break;
  285. }
  286. case Smb4KSambaOptionsInfo::Share:
  287. {
  288. if ( (*it)->port() != -1 ||
  289. (*it)->remount() ||
  290. #ifndef __FreeBSD__
  291. (*it)->kerberos() != Smb4KSettings::useKerberos() ||
  292. !(*it)->filesystem().isEmpty() ||
  293. (*it)->writeAccess() != write_access ||
  294. #endif
  295. !(*it)->uid().isEmpty() ||
  296. !(*it)->gid().isEmpty() )
  297. {
  298. ts << "[" << (*it)->itemName() << "]" << endl;
  299. ts << "port=" << ((*it)->port() != -1 ? (*it)->port() :
  300. Smb4KSettings::remotePort()) << endl;
  301. ts << "remount=" << ((*it)->remount() ? "true" : "false") << endl;
  302. #ifndef __FreeBSD__
  303. // FreeBSD does not know Kerberos for mounting:
  304. ts << "kerberos=" << ((*it)->kerberos() ? "true" : "false") << endl;
  305. ts << "filesystem=" << (!(*it)->filesystem().stripWhiteSpace().isEmpty() ?
  306. (*it)->filesystem() : default_filesystem) << endl;
  307. ts << "write access=" << ((*it)->writeAccess() ? "true" : "false") << endl;
  308. #endif
  309. ts << "uid=" << (!(*it)->uid().stripWhiteSpace().isEmpty() ?
  310. (*it)->uid() : Smb4KSettings::userID()) << endl;
  311. ts << "gid=" << (!(*it)->gid().stripWhiteSpace().isEmpty() ?
  312. (*it)->gid() : Smb4KSettings::groupID()) << endl;
  313. }
  314. else
  315. {
  316. // Do nothing
  317. }
  318. break;
  319. }
  320. default:
  321. {
  322. break;
  323. }
  324. }
  325. ts << endl;
  326. }
  327. file.close();
  328. }
  329. }
  330. else
  331. {
  332. file.remove();
  333. }
  334. }
  335. void Smb4KSambaOptionsHandler::remount( Smb4KShare *share, bool yes )
  336. {
  337. if ( share )
  338. {
  339. Smb4KSambaOptionsInfo *info = NULL;
  340. if ( (info = find_item( share->name() )) )
  341. {
  342. info->setRemount( yes );
  343. }
  344. else if ( !info && yes )
  345. {
  346. info = new Smb4KSambaOptionsInfo( share );
  347. info->setRemount( yes );
  348. m_list.append( info );
  349. }
  350. }
  351. }
  352. void Smb4KSambaOptionsHandler::sync()
  353. {
  354. write_options();
  355. }
  356. Smb4KSambaOptionsInfo *Smb4KSambaOptionsHandler::find_item( const TQString &item, bool exactMatch )
  357. {
  358. // If the list is empty, we'll read the file.
  359. if ( m_list.isEmpty() )
  360. {
  361. read_options();
  362. }
  363. TQString host = item.section( "/", 2, 2 ).stripWhiteSpace();
  364. Smb4KSambaOptionsInfo *info = NULL;
  365. if ( !item.stripWhiteSpace().isEmpty() )
  366. {
  367. for ( TQValueList<Smb4KSambaOptionsInfo *>::ConstIterator it = m_list.begin();
  368. it != m_list.end(); ++it )
  369. {
  370. if ( TQString::compare( item.lower(), (*it)->itemName().lower() ) == 0 )
  371. {
  372. info = *it;
  373. break;
  374. }
  375. else if ( TQString::compare( host.lower(), (*it)->itemName().lower() ) == 0 )
  376. {
  377. if ( !info && !exactMatch )
  378. {
  379. info = *it;
  380. }
  381. continue;
  382. }
  383. else
  384. {
  385. continue;
  386. }
  387. }
  388. }
  389. return info;
  390. }
  391. const TQString Smb4KSambaOptionsHandler::smbclientOptions( const TQString &share )
  392. {
  393. // Get the global Samba options
  394. (void) globalSambaOptions();
  395. Smb4KSambaOptionsInfo *info = find_item( share );
  396. TQString args = TQString();
  397. // Get the strings that are needed to put the
  398. // argument list together:
  399. TQString resolve_order = (!Smb4KSettings::nameResolveOrder().isEmpty() &&
  400. TQString::compare( Smb4KSettings::nameResolveOrder(),
  401. m_samba_options["name resolve order"] ) != 0) ?
  402. Smb4KSettings::nameResolveOrder() :
  403. TQString();
  404. TQString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
  405. TQString::compare( Smb4KSettings::netBIOSName(),
  406. m_samba_options["netbios name"] ) != 0) ?
  407. Smb4KSettings::netBIOSName() :
  408. TQString();
  409. TQString netbios_scope = (!Smb4KSettings::netBIOSScope().isEmpty() &&
  410. TQString::compare( Smb4KSettings::netBIOSScope(),
  411. m_samba_options["netbios scope"] ) != 0) ?
  412. Smb4KSettings::netBIOSScope() :
  413. TQString();
  414. TQString socket_options = (!Smb4KSettings::socketOptions().isEmpty() &&
  415. TQString::compare( Smb4KSettings::socketOptions(),
  416. m_samba_options["socket options"] ) != 0) ?
  417. Smb4KSettings::socketOptions() :
  418. TQString();
  419. bool kerberos = info ?
  420. info->kerberos() :
  421. Smb4KSettings::useKerberos();
  422. int port = info && info->port() != -1 ?
  423. info->port() :
  424. Smb4KSettings::remotePort();
  425. // Options that are not customizable:
  426. args.append( !resolve_order.isEmpty() ?
  427. TQString( " -R '%1'" ).tqarg( resolve_order ) :
  428. TQString() );
  429. args.append( !netbios_name.isEmpty() ?
  430. TQString( " -n '%1'" ).tqarg( netbios_name ) :
  431. TQString() );
  432. args.append( !netbios_scope.isEmpty() ?
  433. TQString( " -i '%1'" ).tqarg( netbios_scope ) :
  434. TQString() );
  435. args.append( !socket_options.isEmpty() ?
  436. TQString( " -O '%1'" ).tqarg( socket_options ) :
  437. TQString() );
  438. args.append( Smb4KSettings::bufferSize() != 65520 ?
  439. TQString( " -b %1" ).tqarg( Smb4KSettings::bufferSize() ) :
  440. TQString() );
  441. args.append( Smb4KSettings::machineAccount() ? " -P" : TQString() );
  442. switch ( Smb4KSettings::signingState() )
  443. {
  444. case Smb4KSettings::EnumSigningState::None:
  445. {
  446. // The user does not want this setting
  447. // to be used.
  448. break;
  449. }
  450. case Smb4KSettings::EnumSigningState::On:
  451. {
  452. args.append( " -S on" );
  453. break;
  454. }
  455. case Smb4KSettings::EnumSigningState::Off:
  456. {
  457. args.append( " -S off" );
  458. break;
  459. }
  460. case Smb4KSettings::EnumSigningState::Required:
  461. {
  462. args.append( " -S required" );
  463. break;
  464. }
  465. default:
  466. {
  467. break;
  468. }
  469. }
  470. args.append( kerberos ? " -k" : TQString() );
  471. args.append( TQString( " -p %1" ).tqarg( port ) );
  472. return args;
  473. }
  474. const TQString Smb4KSambaOptionsHandler::nmblookupOptions( bool with_broadcast )
  475. {
  476. // Get the global Samba options
  477. (void) globalSambaOptions();
  478. TQString args = TQString();
  479. TQString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
  480. TQString::compare( Smb4KSettings::netBIOSName(),
  481. m_samba_options["netbios name"] ) != 0) ?
  482. Smb4KSettings::netBIOSName() :
  483. TQString();
  484. TQString netbios_scope = (!Smb4KSettings::netBIOSScope().isEmpty() &&
  485. TQString::compare( Smb4KSettings::netBIOSScope(),
  486. m_samba_options["netbios scope"] ) != 0) ?
  487. Smb4KSettings::netBIOSScope() :
  488. TQString();
  489. TQString socket_options = (!Smb4KSettings::socketOptions().isEmpty() &&
  490. TQString::compare( Smb4KSettings::socketOptions(),
  491. m_samba_options["socket options"] ) != 0) ?
  492. Smb4KSettings::socketOptions() :
  493. TQString();
  494. TQString domain = (!Smb4KSettings::domainName().isEmpty() &&
  495. TQString::compare( Smb4KSettings::domainName(),
  496. m_samba_options["workgroup"] ) != 0) ?
  497. Smb4KSettings::domainName() :
  498. TQString();
  499. args.append( !netbios_name.isEmpty() ?
  500. TQString( " -n '%1'" ).tqarg( netbios_name ) :
  501. TQString() );
  502. args.append( !netbios_scope.isEmpty() ?
  503. TQString( " -i '%1'" ).tqarg( netbios_scope ) :
  504. TQString() );
  505. args.append( !socket_options.isEmpty() ?
  506. TQString( " -O '%1'" ).tqarg( socket_options ) :
  507. TQString() );
  508. args.append( !domain.isEmpty() ?
  509. TQString( " -W '%1'" ).tqarg( domain ) :
  510. TQString() );
  511. args.append( (!Smb4KSettings::broadcastAddress().isEmpty() &&
  512. with_broadcast) ?
  513. TQString( " -B %1" ).tqarg( Smb4KSettings::broadcastAddress() ) :
  514. TQString() );
  515. args.append( Smb4KSettings::usePort137() ?
  516. " -r" :
  517. TQString() );
  518. return args;
  519. }
  520. const TQString Smb4KSambaOptionsHandler::netOptions( int command, const TQString &networkItem, const TQString &protocol )
  521. {
  522. TQString args = TQString();
  523. Smb4KSambaOptionsInfo *info = find_item( networkItem );
  524. TQString protocol_hint;
  525. // Determine the protocol hint specified by the user:
  526. switch ( Smb4KSettings::protocolHint() )
  527. {
  528. case Smb4KSettings::EnumProtocolHint::Automatic:
  529. {
  530. // In this case the user leaves it to the net
  531. // command to determine the right protocol.
  532. protocol_hint = TQString();
  533. break;
  534. }
  535. case Smb4KSettings::EnumProtocolHint::RPC:
  536. {
  537. protocol_hint = "rpc";
  538. break;
  539. }
  540. case Smb4KSettings::EnumProtocolHint::RAP:
  541. {
  542. protocol_hint = "rap";
  543. break;
  544. }
  545. case Smb4KSettings::EnumProtocolHint::ADS:
  546. {
  547. protocol_hint = "ads";
  548. break;
  549. }
  550. default:
  551. {
  552. protocol_hint = TQString();
  553. break;
  554. }
  555. }
  556. TQString default_protocol = (info && !info->protocol().isEmpty()) ?
  557. info->protocol() :
  558. protocol_hint;
  559. TQString netbios_name = (!Smb4KSettings::netBIOSName().isEmpty() &&
  560. TQString::compare( Smb4KSettings::netBIOSName(),
  561. m_samba_options["netbios name"] ) != 0) ?
  562. Smb4KSettings::netBIOSName() :
  563. TQString();
  564. TQString domain = (!Smb4KSettings::domainName().isEmpty() &&
  565. TQString::compare( Smb4KSettings::domainName(),
  566. m_samba_options["workgroup"] ) != 0) ?
  567. Smb4KSettings::domainName() :
  568. TQString();
  569. int port = (info && info->port() != -1) ?
  570. info->port() :
  571. Smb4KSettings::remotePort();
  572. // Add command specific arguments:
  573. switch ( command )
  574. {
  575. case Share:
  576. {
  577. // We can only use the RAP or RPC protocol here.
  578. if ( !protocol.stripWhiteSpace().isEmpty() )
  579. {
  580. // Protocol can only be defined by us developers,
  581. // and we should know what we are doing. So, no
  582. // checks for the right protocol here:
  583. args.append( TQString( " %1" ).tqarg( protocol ) );
  584. }
  585. else
  586. {
  587. args.append( TQString( " %1" ).tqarg( TQString::compare( default_protocol, "ads" ) != 0 ?
  588. default_protocol :
  589. TQString() /* FIXME: Is that the best way how to do it? */) );
  590. }
  591. args.append( " share -l" );
  592. break;
  593. }
  594. case ServerDomain:
  595. {
  596. // NOTE: Since version 3.0.25, the command 'net rap server domain ...'
  597. // will through an error. We have to use 'net rap server ...'. This is
  598. // also compatible with earlier version.
  599. // This only works with the rap protocol:
  600. args.append( " rap server" );
  601. break;
  602. }
  603. case LookupHost:
  604. {
  605. // Check that the server name is present:
  606. if ( networkItem.stripWhiteSpace().isEmpty() )
  607. {
  608. Smb4KError::error( ERROR_NET_COMMAND, args.stripWhiteSpace() );
  609. return args; // still empty
  610. }
  611. // This lookup command takes no protocol:
  612. args.append( TQString( " lookup host %1" ).tqarg( networkItem ) );
  613. break;
  614. }
  615. case LookupMaster:
  616. {
  617. // Check that the domain name is present:
  618. if ( networkItem.stripWhiteSpace().isEmpty() )
  619. {
  620. Smb4KError::error( ERROR_NET_COMMAND, args.stripWhiteSpace() );
  621. return args; // still empty
  622. }
  623. // This lookup command takes no protocol:
  624. args.append( TQString( " lookup master '%1'" ).tqarg( networkItem ) );
  625. break;
  626. }
  627. case Domain:
  628. {
  629. // This only works with the rap protocol:
  630. args.append( " rap domain" );
  631. break;
  632. }
  633. default:
  634. {
  635. // Bypass the rest and return an
  636. // empty string:
  637. return args;
  638. }
  639. }
  640. args.append( !domain.isEmpty() ?
  641. TQString( " -W '%1'" ).tqarg( domain ) :
  642. TQString() );
  643. args.append( !netbios_name.isEmpty() ?
  644. TQString( " -n '%1'" ).tqarg( netbios_name ) :
  645. TQString() );
  646. args.append( Smb4KSettings::machineAccount() ?
  647. " -P" :
  648. TQString() );
  649. args.append( TQString( " -p %1" ).tqarg( port ) );
  650. return args;
  651. }
  652. const TQString Smb4KSambaOptionsHandler::mountOptions( const TQString &share )
  653. {
  654. Smb4KSambaOptionsInfo *info = find_item( share );
  655. TQString args;
  656. // Read the global Samba options from smb.conf:
  657. (void) globalSambaOptions();
  658. // Get the strings needed to put the argument list together:
  659. TQString uid = (info && !info->uid().isEmpty()) ?
  660. info->uid() :
  661. Smb4KSettings::userID();
  662. TQString gid = (info && !info->gid().isEmpty()) ?
  663. info->gid() :
  664. Smb4KSettings::groupID();
  665. TQString charset, codepage;
  666. switch ( Smb4KSettings::clientCharset() )
  667. {
  668. case Smb4KSettings::EnumClientCharset::default_charset:
  669. {
  670. charset = m_samba_options["unix charset"].lower(); // maybe empty
  671. break;
  672. }
  673. case Smb4KSettings::EnumClientCharset::iso8859_1:
  674. {
  675. charset = "iso8859-1";
  676. break;
  677. }
  678. case Smb4KSettings::EnumClientCharset::iso8859_2:
  679. {
  680. charset = "iso8859-2";
  681. break;
  682. }
  683. case Smb4KSettings::EnumClientCharset::iso8859_3:
  684. {
  685. charset = "iso8859-3";
  686. break;
  687. }
  688. case Smb4KSettings::EnumClientCharset::iso8859_4:
  689. {
  690. charset = "iso8859-4";
  691. break;
  692. }
  693. case Smb4KSettings::EnumClientCharset::iso8859_5:
  694. {
  695. charset = "iso8859-5";
  696. break;
  697. }
  698. case Smb4KSettings::EnumClientCharset::iso8859_6:
  699. {
  700. charset = "iso8859-6";
  701. break;
  702. }
  703. case Smb4KSettings::EnumClientCharset::iso8859_7:
  704. {
  705. charset = "iso8859-7";
  706. break;
  707. }
  708. case Smb4KSettings::EnumClientCharset::iso8859_8:
  709. {
  710. charset = "iso8859-8";
  711. break;
  712. }
  713. case Smb4KSettings::EnumClientCharset::iso8859_9:
  714. {
  715. charset = "iso8859-9";
  716. break;
  717. }
  718. case Smb4KSettings::EnumClientCharset::iso8859_13:
  719. {
  720. charset = "iso8859-13";
  721. break;
  722. }
  723. case Smb4KSettings::EnumClientCharset::iso8859_14:
  724. {
  725. charset = "iso8859-14";
  726. break;
  727. }
  728. case Smb4KSettings::EnumClientCharset::iso8859_15:
  729. {
  730. charset = "iso8859-15";
  731. break;
  732. }
  733. case Smb4KSettings::EnumClientCharset::utf8:
  734. {
  735. charset = "utf8";
  736. break;
  737. }
  738. case Smb4KSettings::EnumClientCharset::koi8_r:
  739. {
  740. charset = "koi8-r";
  741. break;
  742. }
  743. case Smb4KSettings::EnumClientCharset::koi8_u:
  744. {
  745. charset = "koi8-u";
  746. break;
  747. }
  748. case Smb4KSettings::EnumClientCharset::koi8_ru:
  749. {
  750. charset = "koi8-ru";
  751. break;
  752. }
  753. case Smb4KSettings::EnumClientCharset::cp1251:
  754. {
  755. charset = "cp1251";
  756. break;
  757. }
  758. case Smb4KSettings::EnumClientCharset::gb2312:
  759. {
  760. charset = "gb2312";
  761. break;
  762. }
  763. case Smb4KSettings::EnumClientCharset::big5:
  764. {
  765. charset = "big5";
  766. break;
  767. }
  768. case Smb4KSettings::EnumClientCharset::euc_jp:
  769. {
  770. charset = "euc-jp";
  771. break;
  772. }
  773. case Smb4KSettings::EnumClientCharset::euc_kr:
  774. {
  775. charset = "euc-kr";
  776. break;
  777. }
  778. case Smb4KSettings::EnumClientCharset::tis_620:
  779. {
  780. charset = "tis-620";
  781. break;
  782. }
  783. default:
  784. {
  785. break;
  786. }
  787. }
  788. switch ( Smb4KSettings::serverCodepage() )
  789. {
  790. case Smb4KSettings::EnumServerCodepage::default_codepage:
  791. {
  792. codepage = m_samba_options["dos charset"].lower(); // maybe empty
  793. break;
  794. }
  795. case Smb4KSettings::EnumServerCodepage::cp437:
  796. {
  797. codepage = "cp437";
  798. break;
  799. }
  800. case Smb4KSettings::EnumServerCodepage::cp720:
  801. {
  802. codepage = "cp720";
  803. break;
  804. }
  805. case Smb4KSettings::EnumServerCodepage::cp737:
  806. {
  807. codepage = "cp737";
  808. break;
  809. }
  810. case Smb4KSettings::EnumServerCodepage::cp775:
  811. {
  812. codepage = "cp775";
  813. break;
  814. }
  815. case Smb4KSettings::EnumServerCodepage::cp850:
  816. {
  817. codepage = "cp850";
  818. break;
  819. }
  820. case Smb4KSettings::EnumServerCodepage::cp852:
  821. {
  822. codepage = "cp852";
  823. break;
  824. }
  825. case Smb4KSettings::EnumServerCodepage::cp855:
  826. {
  827. codepage = "cp855";
  828. break;
  829. }
  830. case Smb4KSettings::EnumServerCodepage::cp857:
  831. {
  832. codepage = "cp857";
  833. break;
  834. }
  835. case Smb4KSettings::EnumServerCodepage::cp858:
  836. {
  837. codepage = "cp858";
  838. break;
  839. }
  840. case Smb4KSettings::EnumServerCodepage::cp860:
  841. {
  842. codepage = "cp860";
  843. break;
  844. }
  845. case Smb4KSettings::EnumServerCodepage::cp861:
  846. {
  847. codepage = "cp861";
  848. break;
  849. }
  850. case Smb4KSettings::EnumServerCodepage::cp862:
  851. {
  852. codepage = "cp862";
  853. break;
  854. }
  855. case Smb4KSettings::EnumServerCodepage::cp863:
  856. {
  857. codepage = "cp863";
  858. break;
  859. }
  860. case Smb4KSettings::EnumServerCodepage::cp864:
  861. {
  862. codepage = "cp864";
  863. break;
  864. }
  865. case Smb4KSettings::EnumServerCodepage::cp865:
  866. {
  867. codepage = "cp865";
  868. break;
  869. }
  870. case Smb4KSettings::EnumServerCodepage::cp866:
  871. {
  872. codepage = "cp866";
  873. break;
  874. }
  875. case Smb4KSettings::EnumServerCodepage::cp869:
  876. {
  877. codepage = "cp869";
  878. break;
  879. }
  880. case Smb4KSettings::EnumServerCodepage::cp874:
  881. {
  882. codepage = "cp874";
  883. break;
  884. }
  885. case Smb4KSettings::EnumServerCodepage::cp932:
  886. {
  887. codepage = "cp932";
  888. break;
  889. }
  890. case Smb4KSettings::EnumServerCodepage::cp936:
  891. {
  892. codepage = "cp936";
  893. break;
  894. }
  895. case Smb4KSettings::EnumServerCodepage::cp949:
  896. {
  897. codepage = "cp949";
  898. break;
  899. }
  900. case Smb4KSettings::EnumServerCodepage::cp950:
  901. {
  902. codepage = "cp950";
  903. break;
  904. }
  905. case Smb4KSettings::EnumServerCodepage::cp1250:
  906. {
  907. codepage = "cp1250";
  908. break;
  909. }
  910. case Smb4KSettings::EnumServerCodepage::cp1251:
  911. {
  912. codepage = "cp1251";
  913. break;
  914. }
  915. case Smb4KSettings::EnumServerCodepage::cp1252:
  916. {
  917. codepage = "cp1252";
  918. break;
  919. }
  920. case Smb4KSettings::EnumServerCodepage::cp1253:
  921. {
  922. codepage = "cp1253";
  923. break;
  924. }
  925. case Smb4KSettings::EnumServerCodepage::cp1254:
  926. {
  927. codepage = "cp1254";
  928. break;
  929. }
  930. case Smb4KSettings::EnumServerCodepage::cp1255:
  931. {
  932. codepage = "cp1255";
  933. break;
  934. }
  935. case Smb4KSettings::EnumServerCodepage::cp1256:
  936. {
  937. codepage = "cp1256";
  938. break;
  939. }
  940. case Smb4KSettings::EnumServerCodepage::cp1257:
  941. {
  942. codepage = "cp1257";
  943. break;
  944. }
  945. case Smb4KSettings::EnumServerCodepage::cp1258:
  946. {
  947. codepage = "cp1258";
  948. break;
  949. }
  950. case Smb4KSettings::EnumServerCodepage::unicode:
  951. {
  952. codepage = "tqunicode";
  953. break;
  954. }
  955. default:
  956. {
  957. break;
  958. }
  959. }
  960. #ifndef __FreeBSD__
  961. TQString netbios_name = !Smb4KSettings::netBIOSName().isEmpty() ?
  962. Smb4KSettings::netBIOSName() :
  963. m_samba_options["netbios name"];
  964. TQString socket_options = (!Smb4KSettings::socketOptions().isEmpty() &&
  965. TQString::compare( Smb4KSettings::socketOptions(),
  966. m_samba_options["socket options"] ) != 0) ?
  967. Smb4KSettings::socketOptions() :
  968. TQString();
  969. TQString netbios_scope = (!Smb4KSettings::netBIOSScope().isEmpty() &&
  970. TQString::compare( Smb4KSettings::netBIOSScope(),
  971. m_samba_options["netbios scope"] ) != 0) ?
  972. Smb4KSettings::netBIOSScope() :
  973. TQString();
  974. int port = info && info->port() != -1 ?
  975. info->port() :
  976. Smb4KSettings::remotePort();
  977. bool kerberos = info ?
  978. info->kerberos() :
  979. Smb4KSettings::useKerberos();
  980. bool read_write = info ?
  981. info->writeAccess() :
  982. (Smb4KSettings::writeAccess() == Smb4KSettings::EnumWriteAccess::ReadWrite);
  983. // Compile the arguments list:
  984. args.append( !netbios_name.isEmpty() ?
  985. TQString( "netbiosname='%1'," ).tqarg( netbios_name ) :
  986. TQString() );
  987. args.append( !uid.isEmpty() ?
  988. TQString( "uid=%1," ).tqarg( uid ) :
  989. TQString() );
  990. args.append( !gid.isEmpty() ?
  991. TQString( "gid=%1," ).tqarg( gid ) :
  992. TQString() );
  993. args.append( TQString( "port=%1," ).tqarg( port ) );
  994. args.append( !charset.isEmpty() ?
  995. TQString( "iocharset=%1," ).tqarg( charset ) :
  996. TQString() );
  997. args.append( read_write ? "rw," : "ro," );
  998. switch ( Smb4KSettings::filesystem() )
  999. {
  1000. case Smb4KSettings::EnumFilesystem::CIFS:
  1001. {
  1002. args.append( !Smb4KSettings::fileMask().isEmpty() ?
  1003. TQString( "file_mode=%1," ).tqarg( Smb4KSettings::fileMask() ) :
  1004. TQString() );
  1005. args.append( !Smb4KSettings::directoryMask().isEmpty() ?
  1006. TQString( "dir_mode=%1," ).tqarg( Smb4KSettings::directoryMask() ) :
  1007. TQString() );
  1008. args.append( Smb4KSettings::permissionChecks() ?
  1009. "perm," :
  1010. "noperm," );
  1011. args.append( Smb4KSettings::clientControlsIDs() ?
  1012. "setuids," :
  1013. "nosetuids," );
  1014. args.append( Smb4KSettings::serverInodeNumbers() ?
  1015. "serverino," :
  1016. "noserverino," );
  1017. args.append( Smb4KSettings::inodeDataCaching() ?
  1018. "directio," :
  1019. TQString() ); // FIXME: Does 'nodirectio' exist?
  1020. args.append( Smb4KSettings::translateReservedChars() ?
  1021. "mapchars," :
  1022. "nomapchars," );
  1023. args.append( Smb4KSettings::noLocking() ?
  1024. "nolock," :
  1025. TQString() ); // FIXME: Does 'lock' exist?
  1026. args.append( !Smb4KSettings::customCIFSOptions().isEmpty() ?
  1027. Smb4KSettings::customCIFSOptions() :
  1028. TQString() );
  1029. break;
  1030. }
  1031. case Smb4KSettings::EnumFilesystem::SMBFS:
  1032. {
  1033. args.append( !socket_options.isEmpty() ?
  1034. TQString( "sockopt='%1'," ).tqarg( socket_options ) :
  1035. TQString() );
  1036. args.append( !netbios_scope.isEmpty() ?
  1037. TQString( "scope=%1," ).tqarg( netbios_scope ) :
  1038. TQString() );
  1039. args.append( !codepage.isEmpty() ?
  1040. TQString( "codepage=%1," ).tqarg( codepage ) :
  1041. TQString() );
  1042. args.append( !Smb4KSettings::fileMask().isEmpty() ?
  1043. TQString( "fmask=%1," ).tqarg( Smb4KSettings::fileMask() ) :
  1044. TQString() );
  1045. args.append( !Smb4KSettings::directoryMask().isEmpty() ?
  1046. TQString( "dmask=%1," ).tqarg( Smb4KSettings::directoryMask() ) :
  1047. TQString() );
  1048. args.append( kerberos ? "krb," : TQString() );
  1049. args.append( Smb4KSettings::cachingTime() != 1000 ?
  1050. TQString( "ttl=%1," ).tqarg( Smb4KSettings::cachingTime() ) :
  1051. TQString() );
  1052. args.append( Smb4KSettings::unicodeSupport() ?
  1053. "tqunicode," :
  1054. TQString() );
  1055. args.append( Smb4KSettings::largeFileSystemSupport() ?
  1056. "lfs," :
  1057. TQString() );
  1058. break;
  1059. }
  1060. default:
  1061. {
  1062. break;
  1063. }
  1064. }
  1065. #else
  1066. // Compile the arguments list:
  1067. args.append( !uid.isEmpty() ?
  1068. TQString( " -u %1" ).tqarg( uid ) :
  1069. TQString() );
  1070. args.append( !gid.isEmpty() ?
  1071. TQString( " -g %1" ).tqarg( gid ) :
  1072. TQString() );
  1073. args.append( !charset.isEmpty() && !codepage.isEmpty() ?
  1074. TQString( " -E %1:%2" ).tqarg( charset, codepage ) :
  1075. TQString() );
  1076. args.append( !Smb4KSettings::fileMask().isEmpty() ?
  1077. TQString( " -f %1" ).tqarg( Smb4KSettings::fileMask() ) :
  1078. TQString() );
  1079. args.append( !Smb4KSettings::directoryMask().isEmpty() ?
  1080. TQString( " -d %1" ).tqarg( Smb4KSettings::directoryMask() ) :
  1081. TQString() );
  1082. // NOTE: Under FreeBSD the port must be managed by the mounter.
  1083. // FIXME: If the manual page was of more use, we could probably implement
  1084. // more of the arguments that are available for mount_smbfs.
  1085. #endif
  1086. return args;
  1087. }
  1088. void Smb4KSambaOptionsHandler::read_smb_conf()
  1089. {
  1090. // Clear the options list before reading.
  1091. m_samba_options.clear();
  1092. TQStringList paths;
  1093. paths << "/etc";
  1094. paths << "/etc/samba";
  1095. paths << "/usr/local/etc";
  1096. paths << "/usr/local/etc/samba";
  1097. TQFile f( "smb.conf" );
  1098. TQStringList contents;
  1099. // Locate the file and read its contents:
  1100. for ( TQStringList::Iterator it = paths.begin(); it != paths.end(); ++it )
  1101. {
  1102. TQDir::setCurrent( *it );
  1103. if ( f.exists() )
  1104. {
  1105. if ( f.open( IO_ReadOnly ) )
  1106. {
  1107. TQTextStream ts( &f );
  1108. ts.setEncoding( TQTextStream::Locale );
  1109. contents = TQStringList::split( '\n', ts.read(), false );
  1110. }
  1111. f.close();
  1112. break;
  1113. }
  1114. else
  1115. {
  1116. continue;
  1117. }
  1118. }
  1119. // Process the file contents.
  1120. for ( TQStringList::Iterator it = contents.erase( contents.begin(), ++(contents.find( "[global]" )) ); it != contents.end(); ++it )
  1121. {
  1122. if ( (*it).stripWhiteSpace().startsWith( "#" ) || (*it).stripWhiteSpace().startsWith( ";" ) )
  1123. {
  1124. *it = TQString();
  1125. }
  1126. else if ( (*it).stripWhiteSpace().startsWith( "include" ) )
  1127. {
  1128. // Put the contents of the included at this position.
  1129. TQString file = (*it).section( "=", 1, 1 ).stripWhiteSpace();
  1130. *it = TQString();
  1131. f.setName( file );
  1132. TQStringList include;
  1133. if ( f.exists() )
  1134. {
  1135. if ( f.open( IO_ReadOnly ) )
  1136. {
  1137. TQTextStream ts( &f );
  1138. ts.setEncoding( TQTextStream::Locale );
  1139. include = TQStringList::split( '\n', ts.read(), false );
  1140. }
  1141. f.close();
  1142. }
  1143. for ( TQStringList::Iterator i = include.begin(); i != include.end(); ++i )
  1144. {
  1145. if ( !(*i).stripWhiteSpace().isEmpty() )
  1146. {
  1147. contents.insert( it, *i );
  1148. continue;
  1149. }
  1150. else
  1151. {
  1152. continue;
  1153. }
  1154. }
  1155. continue;
  1156. }
  1157. else if ( (*it).startsWith( "[" ) )
  1158. {
  1159. contents.erase( it, contents.end() );
  1160. break;
  1161. }
  1162. else
  1163. {
  1164. continue;
  1165. }
  1166. }
  1167. contents.remove( TQString() );
  1168. // Write all options into the map:
  1169. for ( TQStringList::ConstIterator it = contents.begin(); it != contents.end(); ++it )
  1170. {
  1171. TQString key = (*it).section( "=", 0, 0 ).stripWhiteSpace().lower();
  1172. m_samba_options[key] = TQString( (*it).section( "=", 1, 1 ).stripWhiteSpace().upper() );
  1173. }
  1174. // Post-processing. Some values should be entered with their defaults, if they are
  1175. // not already present.
  1176. if ( !m_samba_options.contains( "netbios name" ) )
  1177. {
  1178. size_t hostnamelen = 255;
  1179. char *hostname = new char[hostnamelen];
  1180. if ( gethostname( hostname, hostnamelen ) == -1 )
  1181. {
  1182. int error = errno;
  1183. Smb4KError::error( ERROR_GETTING_HOSTNAME, TQString(), strerror( error ) );
  1184. }
  1185. else
  1186. {
  1187. m_samba_options["netbios name"] = ( TQString( "%1" ).tqarg( hostname ) ).upper();
  1188. }
  1189. delete [] hostname;
  1190. }
  1191. }
  1192. const TQMap<TQString,TQString> &Smb4KSambaOptionsHandler::globalSambaOptions()
  1193. {
  1194. if ( m_samba_options.isEmpty() )
  1195. {
  1196. read_smb_conf();
  1197. }
  1198. return m_samba_options;
  1199. }
  1200. const TQString &Smb4KSambaOptionsHandler::winsServer()
  1201. {
  1202. if ( m_wins_server.isEmpty() )
  1203. {
  1204. (void) globalSambaOptions();
  1205. if ( !m_samba_options["wins server"].isEmpty() )
  1206. {
  1207. m_wins_server = m_samba_options["wins server"];
  1208. }
  1209. else if ( !m_samba_options["wins support"].isEmpty() &&
  1210. (TQString::compare( m_samba_options["wins support"].lower(), "yes" ) == 0 ||
  1211. TQString::compare( m_samba_options["wins support"].lower(), "true" ) == 0) )
  1212. {
  1213. m_wins_server = "127.0.0.1";
  1214. }
  1215. }
  1216. return m_wins_server;
  1217. }
  1218. void Smb4KSambaOptionsHandler::addItem( Smb4KSambaOptionsInfo *info, bool s )
  1219. {
  1220. Smb4KSambaOptionsInfo *item = find_item( info->itemName() );
  1221. if ( item && TQString::compare( item->itemName().lower(), info->itemName().lower() ) == 0 )
  1222. {
  1223. item->setPort( info->port() );
  1224. #ifndef __FreeBSD__
  1225. item->setFilesystem( info->filesystem() );
  1226. item->setWriteAccess( info->writeAccess() );
  1227. #endif
  1228. item->setRemount( info->remount() );
  1229. item->setProtocol( info->protocol() );
  1230. item->setKerberos( info->kerberos() );
  1231. item->setUID( info->uid() );
  1232. item->setGID( info->gid() );
  1233. delete info;
  1234. }
  1235. else
  1236. {
  1237. m_list.append( info );
  1238. }
  1239. if ( s )
  1240. {
  1241. sync();
  1242. }
  1243. }
  1244. void Smb4KSambaOptionsHandler::removeItem( const TQString &name, bool s )
  1245. {
  1246. Smb4KSambaOptionsInfo *item = find_item( name );
  1247. if ( item && TQString::compare( item->itemName().lower(), name.lower() ) == 0 )
  1248. {
  1249. m_list.remove( item );
  1250. delete item;
  1251. }
  1252. if ( s )
  1253. {
  1254. sync();
  1255. }
  1256. }
  1257. #include "smb4ksambaoptionshandler.moc"