26#include <QtCore/QMutableMapIterator>
27#include <QtCore/QFile>
28#include <QtCore/QRegExp>
29#include <QtCore/QFileInfo>
30#include <QtCore/QTextStream>
31#include <QtCore/QStringList>
43 "/etc/samba/smb.conf",
45 "/usr/local/etc/smb.conf",
46 "/usr/local/samba/lib/smb.conf",
47 "/usr/samba/lib/smb.conf",
49 "/usr/local/lib/smb.conf"
59 , skipUserShare(false)
72 if (QFile::exists(
"/usr/sbin/smbd")
73 || QFile::exists(
"/usr/local/sbin/smbd")) {
77 kDebug() <<
"Samba is not installed!";
88 if (QFile::exists(filePath)) {
94 kWarning() <<
"KSambaShare: Could not find smb.conf!";
102 const QFileInfo fileInfo(rawString);
103 if (fileInfo.isDir()) {
104 userSharePath = rawString;
109 QByteArray &stdOut, QByteArray &stdErr)
117 process.waitForFinished();
119 stdOut = process.readAllStandardOutput();
120 stdErr = process.readAllStandardError();
121 return process.exitCode();
134 args << QLatin1String(
"-d0") << QLatin1String(
"-s") << QLatin1String(
"--parameter-name")
137 runProcess(QLatin1String(
"testparm"), args, stdOut, stdErr);
142 if (!stdErr.isEmpty()) {
144 err << stdErr.trimmed().split(
'\n');
145 if ((err.count() == 2)
146 && err.at(0).startsWith(
"Load smb config files from")
147 && err.at(1).startsWith(
"Loaded services file OK.")) {
148 kDebug() <<
"Running testparm" << args;
150 kWarning() <<
"We got some errors while running testparm" << stdErr;
154 if (!stdOut.isEmpty()) {
155 return QString::fromLocal8Bit(stdOut.trimmed());
171 args << QLatin1String(
"usershare") << QLatin1String(
"info");
173 runProcess(QLatin1String(
"net"), args, stdOut, stdErr);
175 if (!stdErr.isEmpty()) {
176 if (stdErr.contains(
"You do not have permission to create a usershare")) {
177 skipUserShare =
true;
178 }
else if (stdErr.contains(
"usershares are currently disabled")) {
179 skipUserShare =
true;
184 kWarning() <<
"We got some errors while running 'net usershare info'";
202 for (i = data.constBegin(); i != data.constEnd(); ++i) {
203 if (!
dirs.contains(i.value().path())) {
204 dirs << i.value().path();
213 return data.value(shareName);
221 for (i = data.constBegin(); i != data.constEnd(); ++i) {
222 if (i.value().path() == path) {
233 const QRegExp notToMatchRx(QLatin1String(
"[%<>*\?|/\\+=;:\",]"));
234 return (notToMatchRx.indexIn(
name) == -1);
240 for (i = data.constBegin(); i != data.constEnd(); ++i) {
241 if (i.value().path() == path) {
257 QFileInfo pathInfo = path;
259 if (!pathInfo.exists()) {
263 if (!pathInfo.isDir()) {
267 if (pathInfo.isRelative()) {
268 if (pathInfo.makeAbsolute()) {
275 == QLatin1String(
"Yes")) {
276 if (!pathInfo.permission(QFile::ReadUser | QFile::WriteUser)) {
286 const QRegExp aclRx(
"(?:(?:(\\w+\\s*)\\\\|)(\\w+\\s*):([fFrRd]{1})(?:,|))*");
297 == QLatin1String(
"No")) {
318 if (data.contains(shareData.
name())) {
319 if (data.value(shareData.
name()).path() != shareData.
path()) {
325 data.insert(shareData.
name(), shareData);
328 QString guestok = QString(
"guest_ok=%1").arg(
330 ? QLatin1String(
"n") : QLatin1String(
"y"));
332 args << QLatin1String(
"usershare") << QLatin1String(
"add") << shareData.
name()
333 << shareData.
path() << shareData.
comment() << shareData.
acl() << guestok;
335 int ret =
runProcess(QLatin1String(
"net"), args, stdOut, stdErr);
338 if (!stdErr.isEmpty()) {
341 kWarning() <<
"We got some errors while running 'net usershare add'" << args;
356 if (!data.contains(shareData.
name())) {
360 args << QLatin1String(
"usershare") << QLatin1String(
"delete") << shareData.
name();
368 const QRegExp headerRx(QLatin1String(
"^\\s*\\["
369 "([^%<>*\?|/\\+=;:\",]+)"
372 const QRegExp OptValRx(QLatin1String(
"^\\s*([\\w\\d\\s]+)"
377 QString currentShare;
378 QStringList shareList;
380 while (!stream.atEnd()) {
381 const QString line = stream.readLine().trimmed();
383 if (headerRx.exactMatch(line)) {
384 currentShare = headerRx.cap(1).trimmed();
385 shareList << currentShare;
387 if (!data.contains(currentShare)) {
389 shareData.dd->name = currentShare;
390 data.insert(currentShare, shareData);
392 }
else if (OptValRx.exactMatch(line)) {
393 const QString key = OptValRx.cap(1).trimmed();
394 const QString value = OptValRx.cap(2).trimmed();
397 if (key == QLatin1String(
"path")) {
398 shareData.dd->path = value;
399 }
else if (key == QLatin1String(
"comment")) {
400 shareData.dd->comment = value;
401 }
else if (key == QLatin1String(
"usershare_acl")) {
402 shareData.dd->acl = value;
403 }
else if (key == QLatin1String(
"guest_ok")) {
404 shareData.dd->guestPermission = value;
406 kWarning() <<
"Something nasty happen while parsing 'net usershare info'"
407 <<
"share:" << currentShare <<
"key:" << key;
409 }
else if (line.trimmed().isEmpty()) {
416 QMutableMapIterator<QString, KSambaShareData> i(data);
417 while (i.hasNext()) {
419 if (!shareList.contains(i.key())) {
430 kDebug() <<
"path changed:" << path;
435KSambaShare::KSambaShare()
440 if (QFile::exists(d->userSharePath)) {
465 return d->isDirectoryShared(path);
471 return d->isShareNameValid(
name) && d->isShareNameAvailable(
name);
477 return d->shareNames();
483 return d->sharedDirs();
489 return d->getShareByName(
name);
495 return d->getSharesByPath(path);
504#include "moc_ksambashare.cpp"
static KDirWatch * self()
void removeDir(const QString &path)
void addDir(const QString &path, WatchModes watchModes=WatchDirOnly)
void setOutputChannelMode(OutputChannelMode mode)
int execute(int msecs=-1)
void setProgram(const QString &exe, const QStringList &args=QStringList())
This class represents a Samba user share.
QString acl() const
Returns a containing a string describing the permission added to the users, such as "[DOMAIN\]usernam...
@ UserSharePathNotAbsolute
@ UserSharePathNotAllowed
@ UserShareGuestsNotAllowed
@ UserSharePathNotDirectory
KSambaShareData::GuestPermission guestPermission() const
void _k_slotFileChange(const QString &path)
bool isShareNameAvailable(const QString &name) const
KSambaShareData::UserShareError add(const KSambaShareData &shareData)
static bool isSambaInstalled()
bool isDirectoryShared(const QString &path) const
QStringList sharedDirs() const
KSambaSharePrivate(KSambaShare *parent)
QByteArray getNetUserShareInfo()
KSambaShareData::UserShareError remove(const KSambaShareData &shareName) const
KSambaShareData getShareByName(const QString &shareName) const
static QString testparmParamValue(const QString ¶meterName)
KSambaShareData::UserShareError isAclValid(const QString &acl) const
bool isShareNameValid(const QString &name) const
KSambaShareData::UserShareError isPathValid(const QString &path) const
QList< KSambaShareData > getSharesByPath(const QString &path) const
static int runProcess(const QString &progName, const QStringList &args, QByteArray &stdOut, QByteArray &stdErr)
QStringList shareNames() const
KSambaShareData::UserShareError guestsAllowed(const KSambaShareData::GuestPermission &guestok) const
This class lists Samba user shares and monitors them for addition, update and removal.
QString smbConfPath() const
Returns the path to the used smb.conf file or empty string if no file was found.
bool isShareNameAvailable(const QString &name) const
Tests that a share name is valid and does not conflict with system users names or shares.
KSambaShareData getShareByName(const QString &name) const
Returns the KSambaShareData object of the share name.
QList< KSambaShareData > getSharesByPath(const QString &path) const
Returns a list of KSambaShareData matching the path.
QStringList shareNames() const
Returns the list of available shares.
bool isDirectoryShared(const QString &path) const
Whether or not the given path is shared by Samba.
QStringList sharedDirectories() const
Returns a list of all directories shared by local users in Samba.
static KSambaShare * instance()
static QStringList allUserNames()
#define K_GLOBAL_STATIC(TYPE, NAME)
static const int DefaultSambaConfigFilePathListSize
static const char *const DefaultSambaConfigFilePathList[]
const char * name(StandardAction id)