25 #include <QtCore/QMap>
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);
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]+)"
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;
435 KSambaShare::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"
QStringList shareNames() const
Returns the list of available shares.
static KDirWatch * self()
bool isDirectoryShared(const QString &path) const
Whether or not the given path is shared by Samba.
void _k_slotFileChange(const QString &path)
KSambaSharePrivate(KSambaShare *parent)
#define K_GLOBAL_STATIC(TYPE, NAME)
bool isShareNameAvailable(const QString &name) const
This class represents a Samba user share.
static KSambaShare * instance()
void setOutputChannelMode(OutputChannelMode mode)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
static QStringList allUserNames()
bool isShareNameAvailable(const QString &name) const
Tests that a share name is valid and does not conflict with system users names or shares...
KSambaShareData::UserShareError isAclValid(const QString &acl) const
static QString testparmParamValue(const QString ¶meterName)
QList< KSambaShareData > getSharesByPath(const QString &path) const
static bool isSambaInstalled()
bool isDirectoryShared(const QString &path) const
KSambaShareData::UserShareError remove(const KSambaShareData &shareName) const
KSambaShareData::GuestPermission guestPermission() const
KSambaShareData::UserShareError isPathValid(const QString &path) const
static const int DefaultSambaConfigFilePathListSize
bool isShareNameValid(const QString &name) const
QList< KSambaShareData > getSharesByPath(const QString &path) const
Returns a list of KSambaShareData matching the path.
QByteArray getNetUserShareInfo()
QStringList shareNames() const
QStringList sharedDirs() const
int execute(int msecs=-1)
static int runProcess(const QString &progName, const QStringList &args, QByteArray &stdOut, QByteArray &stdErr)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void removeDir(const QString &path)
void addDir(const QString &path, WatchModes watchModes=WatchDirOnly)
QStringList sharedDirectories() const
Returns a list of all directories shared by local users in Samba.
KSambaShareData::UserShareError add(const KSambaShareData &shareData)
QString smbConfPath() const
Returns the path to the used smb.conf file or empty string if no file was found.
QString acl() const
Returns a containing a string describing the permission added to the users, such as "[DOMAIN\]usernam...
KSambaShareData getShareByName(const QString &name) const
Returns the KSambaShareData object of the share name.
static const char *const DefaultSambaConfigFilePathList[]
KSambaShareData getShareByName(const QString &shareName) const
This class lists Samba user shares and monitors them for addition, update and removal.
KSambaShareData::UserShareError guestsAllowed(const KSambaShareData::GuestPermission &guestok) const
void setProgram(const QString &exe, const QStringList &args=QStringList())