summaryrefslogtreecommitdiffstats
path: root/filesharing/simple
diff options
context:
space:
mode:
Diffstat (limited to 'filesharing/simple')
-rw-r--r--filesharing/simple/Makefile.am19
-rw-r--r--filesharing/simple/controlcenter.ui486
-rw-r--r--filesharing/simple/controlcenter.ui.h22
-rw-r--r--filesharing/simple/fileshare.cpp442
-rw-r--r--filesharing/simple/fileshare.desktop169
-rw-r--r--filesharing/simple/fileshare.h82
-rw-r--r--filesharing/simple/groupconfigdlg.cpp418
-rw-r--r--filesharing/simple/groupconfigdlg.h68
-rw-r--r--filesharing/simple/groupconfiggui.ui200
-rw-r--r--filesharing/simple/groupconfiggui.ui.h14
-rw-r--r--filesharing/simple/krichtextlabel.cpp112
-rw-r--r--filesharing/simple/krichtextlabel.h65
12 files changed, 2097 insertions, 0 deletions
diff --git a/filesharing/simple/Makefile.am b/filesharing/simple/Makefile.am
new file mode 100644
index 00000000..7a3e2994
--- /dev/null
+++ b/filesharing/simple/Makefile.am
@@ -0,0 +1,19 @@
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kcm_fileshare.la
+
+kcm_fileshare_la_SOURCES = fileshare.cpp \
+ controlcenter.ui \
+ groupconfiggui.ui \
+ groupconfigdlg.cpp \
+ krichtextlabel.cpp
+
+kcm_fileshare_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+kcm_fileshare_la_LIBADD = ../advanced/propsdlgplugin/libpropsdlgplugin_common.la \
+ ../advanced/nfs/libfilesharenfs.la \
+ ../advanced/kcm_sambaconf/libfilesharesamba.la \
+ $(LIB_KIO)
+
+AM_CPPFLAGS = -I$(srcdir)/../advanced/propsdlgplugin -I../advanced/propsdlgplugin $(all_includes)
+
+xdg_apps_DATA = fileshare.desktop
diff --git a/filesharing/simple/controlcenter.ui b/filesharing/simple/controlcenter.ui
new file mode 100644
index 00000000..eea9166e
--- /dev/null
+++ b/filesharing/simple/controlcenter.ui
@@ -0,0 +1,486 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ControlCenterGUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ControlCenterGUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>525</width>
+ <height>535</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KRichTextLabel">
+ <property name="name">
+ <cstring>infoLbl</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="text">
+ <string>SMB and NFS servers are not installed on this machine, to enable this module the servers must be installed.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>shareGrp</cstring>
+ </property>
+ <property name="title">
+ <string>Enable Local Networ&amp;k File Sharing</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>simpleRadio</cstring>
+ </property>
+ <property name="text">
+ <string>Si&amp;mple sharing</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame4_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>11</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="KRichTextLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>Enable simple sharing to allow users to share folders from their HOME folder, without knowing the root password.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>advancedRadio</cstring>
+ </property>
+ <property name="text">
+ <string>Advanced sharin&amp;g</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame4_2_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>11</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="KRichTextLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>Enable advanced sharing to allow users to share any folders, as long as they have write access to the needed configuration files, or they know the root password.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame" row="0" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>frame4</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>11</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>nfsChk</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Use &amp;NFS (Linux/UNIX)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>sambaChk</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Use Sam&amp;ba (Microsoft(R) Windows(R))</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>allowedUsersBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Allo&amp;wed Users</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>sharedFoldersGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Shared Folders</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Path</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Samba</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>NFS</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>listView</cstring>
+ </property>
+ <property name="selectionMode" stdset="0">
+ <enum>NoSelection</enum>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>shareBtnPnl</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addShareBtn</cstring>
+ </property>
+ <property name="text">
+ <string>A&amp;dd...</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>changeShareBtn</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Chang&amp;e...</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeShareBtn</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Rem&amp;ove</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>advancedRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>nfsChk</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>advancedRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>sambaChk</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>shareGrp</sender>
+ <signal>clicked(int)</signal>
+ <receiver>ControlCenterGUI</receiver>
+ <slot>changedSlot()</slot>
+ </connection>
+ <connection>
+ <sender>simpleRadio</sender>
+ <signal>clicked()</signal>
+ <receiver>ControlCenterGUI</receiver>
+ <slot>changedSlot()</slot>
+ </connection>
+ <connection>
+ <sender>advancedRadio</sender>
+ <signal>clicked()</signal>
+ <receiver>ControlCenterGUI</receiver>
+ <slot>changedSlot()</slot>
+ </connection>
+ <connection>
+ <sender>sambaChk</sender>
+ <signal>clicked()</signal>
+ <receiver>ControlCenterGUI</receiver>
+ <slot>changedSlot()</slot>
+ </connection>
+ <connection>
+ <sender>nfsChk</sender>
+ <signal>clicked()</signal>
+ <receiver>ControlCenterGUI</receiver>
+ <slot>changedSlot()</slot>
+ </connection>
+ <connection>
+ <sender>listView</sender>
+ <signal>selectionChanged()</signal>
+ <receiver>ControlCenterGUI</receiver>
+ <slot>listView_selectionChanged()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>sambaChk</tabstop>
+ <tabstop>nfsChk</tabstop>
+ <tabstop>listView</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">controlcenter.ui.h</include>
+ <include location="local" impldecl="in implementation">krichtextlabel.h</include>
+</includes>
+<signals>
+ <signal>changed()</signal>
+</signals>
+<slots>
+ <slot access="private">changedSlot()</slot>
+ <slot>listView_selectionChanged()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>krichtextlabel.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/filesharing/simple/controlcenter.ui.h b/filesharing/simple/controlcenter.ui.h
new file mode 100644
index 00000000..6fb3f62f
--- /dev/null
+++ b/filesharing/simple/controlcenter.ui.h
@@ -0,0 +1,22 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void ControlCenterGUI::changedSlot()
+{
+ emit changed();
+}
+
+void ControlCenterGUI::listView_selectionChanged()
+{
+ bool empty = listView->selectedItems ().isEmpty();
+ changeShareBtn->setDisabled(empty );
+ removeShareBtn->setDisabled(empty );
+
+}
diff --git a/filesharing/simple/fileshare.cpp b/filesharing/simple/fileshare.cpp
new file mode 100644
index 00000000..a0c5bb06
--- /dev/null
+++ b/filesharing/simple/fileshare.cpp
@@ -0,0 +1,442 @@
+/*
+ Copyright (c) 2002 Laurent Montel <lmontel@mandrakesoft.com>
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include <unistd.h>
+
+#include <qlayout.h>
+#include <qvbuttongroup.h>
+#include <qvgroupbox.h>
+#include <qlabel.h>
+#include <qdir.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+
+#include <kpushbutton.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include <kgenericfactory.h>
+#include <klistview.h>
+#include <kiconloader.h>
+#include <knfsshare.h>
+#include <ksambashare.h>
+#include <kfileshare.h>
+#include <kstandarddirs.h>
+#include <ksimpleconfig.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kuser.h>
+#include <kurl.h>
+#include <kprocess.h>
+#include <krichtextlabel.h>
+
+#include "../advanced/propsdlgplugin/propertiespage.h"
+#include "../advanced/nfs/nfsfile.h"
+#include "../advanced/kcm_sambaconf/sambafile.h"
+
+#include "controlcenter.h"
+#include "fileshare.h"
+#include "groupconfigdlg.h"
+
+typedef KGenericFactory<KFileShareConfig, QWidget > ShareFactory;
+K_EXPORT_COMPONENT_FACTORY (kcm_fileshare, ShareFactory("kcmfileshare") )
+
+
+#define FILESHARECONF "/etc/security/fileshare.conf"
+#define FILESHARE_DEBUG 5009
+
+KFileShareConfig::KFileShareConfig(QWidget *parent, const char *name, const QStringList &):
+ KCModule(ShareFactory::instance(), parent, name)
+{
+ KGlobal::locale()->insertCatalogue("kfileshare");
+
+ QBoxLayout* layout = new QVBoxLayout(this,0,
+ KDialog::spacingHint());
+
+/*
+ QVButtonGroup *box = new QVButtonGroup( i18n("File Sharing"), this );
+ box->layout()->setSpacing( KDialog::spacingHint() );
+ layout->addWidget(box);
+ noSharing=new QRadioButton( i18n("Do &not allow users to share files"), box );
+ sharing=new QRadioButton( i18n("&Allow users to share files from their HOME folder"), box);
+*/
+ m_ccgui = new ControlCenterGUI(this);
+ connect( m_ccgui, SIGNAL( changed()), this, SLOT(configChanged()));
+ connect( m_ccgui->allowedUsersBtn, SIGNAL( clicked()),
+ this, SLOT(allowedUsersBtnClicked()));
+
+ QString path = QString::fromLocal8Bit( getenv( "PATH" ) );
+ path += QString::fromLatin1(":/usr/sbin");
+ QString sambaExec = KStandardDirs::findExe( QString::fromLatin1("smbd"), path );
+ QString nfsExec = KStandardDirs::findExe( QString::fromLatin1("rpc.nfsd"), path );
+
+ if ( nfsExec.isEmpty() && sambaExec.isEmpty())
+ {
+ m_ccgui->shareGrp->setDisabled(true);
+ m_ccgui->sharedFoldersGroupBox->setDisabled(true);
+ }
+ else
+ {
+ if (nfsExec.isEmpty()) {
+ m_ccgui->nfsChk->setDisabled(true);
+ m_ccgui->nfsChk->setChecked(false);
+ QToolTip::add(m_ccgui->nfsChk,i18n("No NFS server installed on this system"));
+ }
+
+ if (sambaExec.isEmpty()) {
+ m_ccgui->sambaChk->setDisabled(true);
+ m_ccgui->sambaChk->setChecked(false);
+ QToolTip::add(m_ccgui->sambaChk,i18n("No Samba server installed on this system"));
+ }
+
+ m_ccgui->infoLbl->hide();
+ layout->addWidget(m_ccgui);
+ updateShareListView();
+ connect( KNFSShare::instance(), SIGNAL( changed()),
+ this, SLOT(updateShareListView()));
+ connect( KSambaShare::instance(), SIGNAL( changed()),
+ this, SLOT(updateShareListView()));
+
+
+ }
+
+ if((getuid() == 0) ||
+ ((KFileShare::shareMode() == KFileShare::Advanced) &&
+ (KFileShare::authorization() == KFileShare::Authorized)))
+ {
+ connect( m_ccgui->addShareBtn, SIGNAL(clicked()),
+ this, SLOT(addShareBtnClicked()));
+ connect( m_ccgui->changeShareBtn, SIGNAL(clicked()),
+ this, SLOT(changeShareBtnClicked()));
+ connect( m_ccgui->removeShareBtn, SIGNAL(clicked()),
+ this, SLOT(removeShareBtnClicked()));
+ m_ccgui->listView->setSelectionMode(QListView::Extended);
+ m_ccgui->shareBtnPnl->setEnabled(true);
+ }
+
+
+ if (getuid()==0) {
+ setButtons(Help|Apply);
+ } else {
+ setButtons(Help);
+ m_ccgui->shareGrp->setDisabled( true );
+ }
+
+ load();
+}
+
+void KFileShareConfig::updateShareListView()
+{
+ m_ccgui->listView->clear();
+ KNFSShare* nfs = KNFSShare::instance();
+ KSambaShare* samba = KSambaShare::instance();
+
+ QStringList dirs = nfs->sharedDirectories();
+ QStringList sambaDirs = samba->sharedDirectories();
+
+ for ( QStringList::ConstIterator it = sambaDirs.begin(); it != sambaDirs.end(); ++it ) {
+ // Do not insert duplicates
+ if (nfs->isDirectoryShared(*it))
+ continue;
+
+ dirs += *it;
+ }
+
+ QPixmap folderPix = SmallIcon("folder",0,KIcon::ShareOverlay);
+ QPixmap okPix = SmallIcon("button_ok");
+ QPixmap cancelPix = SmallIcon("button_cancel");
+
+ for ( QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it ) {
+ KListViewItem* item = new KListViewItem(m_ccgui->listView);
+ item->setText(0,*it);
+ item->setPixmap(0, folderPix);
+
+ if (samba->isDirectoryShared(*it))
+ item->setPixmap(1,okPix);
+ else
+ item->setPixmap(1,cancelPix);
+
+ if (nfs->isDirectoryShared(*it))
+ item->setPixmap(2,okPix);
+ else
+ item->setPixmap(2,cancelPix);
+
+ }
+
+}
+
+void KFileShareConfig::allowedUsersBtnClicked() {
+ GroupConfigDlg dlg(this,m_fileShareGroup,m_restricted,m_rootPassNeeded,
+ m_ccgui->simpleRadio->isChecked());
+ if (dlg.exec() == QDialog::Accepted) {
+ m_fileShareGroup = dlg.fileShareGroup().name();
+ m_restricted = dlg.restricted();
+ m_rootPassNeeded = dlg.rootPassNeeded();
+ configChanged();
+ }
+
+}
+
+
+void KFileShareConfig::load()
+{
+ KSimpleConfig config(QString::fromLatin1(FILESHARECONF),true);
+
+ m_ccgui->shareGrp->setChecked( config.readEntry("FILESHARING", "yes") == "yes" );
+
+ m_restricted = config.readEntry("RESTRICT", "yes") == "yes";
+
+ if (config.readEntry("SHARINGMODE", "simple") == "simple")
+ m_ccgui->simpleRadio->setChecked(true);
+ else
+ m_ccgui->advancedRadio->setChecked(true);
+
+ m_fileShareGroup = config.readEntry("FILESHAREGROUP", "fileshare");
+
+ m_ccgui->sambaChk->setChecked(
+ config.readEntry("SAMBA", "yes") == "yes");
+
+ m_ccgui->nfsChk->setChecked(
+ config.readEntry("NFS", "yes") == "yes");
+
+ m_rootPassNeeded = config.readEntry("ROOTPASSNEEDED", "yes") == "yes";
+
+ m_smbConf = KSambaShare::instance()->smbConfPath();
+}
+
+bool KFileShareConfig::addGroupAccessesToFile(const QString & file) {
+ KProcess chgrp;
+ chgrp << "chgrp" << m_fileShareGroup << file;
+ KProcess chmod;
+ chmod << "chmod" << "g=rw" << file;
+
+ if (!chgrp.start(KProcess::Block) && chgrp.normalExit()) {
+ kdDebug(FILESHARE_DEBUG) << "KFileShareConfig::addGroupAccessesToFile: chgrp failed" << endl;
+ return false;
+
+ }
+
+ if(!chmod.start(KProcess::Block) && chmod.normalExit()) {
+ kdDebug(FILESHARE_DEBUG) << "KFileShareConfig::addGroupAccessesToFile: chmod failed" << endl;
+ return false;
+ }
+
+ return true;
+
+}
+
+bool KFileShareConfig::removeGroupAccessesFromFile(const QString & file) {
+ KProcess chgrp;
+ chgrp << "chgrp" << "root" << file;
+ KProcess chmod;
+ chmod << "chmod" << "g=r" << file;
+
+ if (!chgrp.start(KProcess::Block) && chgrp.normalExit()) {
+ kdDebug(FILESHARE_DEBUG) << "KFileShareConfig::removeGroupAccessesFromFile: chgrp failed" << endl;
+ return false;
+
+ }
+
+ if(!chmod.start(KProcess::Block) && chmod.normalExit()) {
+ kdDebug(FILESHARE_DEBUG) << "KFileShareConfig::removeGroupAccessesFromFile: chmod failed" << endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+bool KFileShareConfig::setGroupAccesses() {
+ if (m_rootPassNeeded || ! m_ccgui->sambaChk->isChecked()) {
+ if (!removeGroupAccessesFromFile(KSambaShare::instance()->smbConfPath()))
+ return false;
+ }
+
+ if (m_rootPassNeeded || ! m_ccgui->nfsChk->isChecked()) {
+ if (!removeGroupAccessesFromFile(KNFSShare::instance()->exportsPath()))
+ return false;
+ }
+
+ if (! m_rootPassNeeded && m_ccgui->sambaChk->isChecked()) {
+ if (!addGroupAccessesToFile(KSambaShare::instance()->smbConfPath()))
+ return false;
+ }
+
+ if (! m_rootPassNeeded && m_ccgui->nfsChk->isChecked()) {
+ if (!addGroupAccessesToFile(KNFSShare::instance()->exportsPath()))
+ return false;
+ }
+
+
+ return true;
+}
+
+void KFileShareConfig::save()
+{
+ setGroupAccesses();
+
+ QDir dir("/etc/security");
+ if ( !dir.exists())
+ dir.mkdir("/etc/security");
+
+ QFile file(FILESHARECONF);
+ if ( ! file.open(IO_WriteOnly)) {
+ KMessageBox::detailedError(this,
+ i18n("Could not save settings."),
+ i18n("Could not open file '%1' for writing: %2").arg(FILESHARECONF).arg(
+ file.errorString() ),
+ i18n("Saving Failed"));
+ return;
+ }
+
+
+ QTextStream stream(&file);
+
+ stream << "FILESHARING=";
+ stream << (m_ccgui->shareGrp->isChecked() ? "yes" : "no");
+
+ stream << "\nRESTRICT=";
+ stream << (m_restricted ? "yes" : "no");
+
+ stream << "\nSHARINGMODE=";
+ stream << (m_ccgui->simpleRadio->isChecked() ? "simple" : "advanced");
+
+ stream << "\nFILESHAREGROUP=";
+ stream << m_fileShareGroup;
+
+ stream << "\nSAMBA=";
+ stream << (m_ccgui->sambaChk->isChecked() ? "yes" : "no");
+
+ stream << "\nNFS=";
+ stream << (m_ccgui->nfsChk->isChecked() ? "yes" : "no");
+
+ stream << "\nROOTPASSNEEDED=";
+ stream << (m_rootPassNeeded ? "yes" : "no");
+
+ stream << "\nSMBCONF=";
+ stream << m_smbConf;
+
+ file.close();
+}
+
+void KFileShareConfig::defaults()
+{
+ m_ccgui->shareGrp->setChecked( false );
+}
+
+QString KFileShareConfig::quickHelp() const
+{
+ return i18n("<h1>File Sharing</h1><p>This module can be used "
+ "to enable file sharing over the network using "
+ "the \"Network File System\" (NFS) or SMB in Konqueror. "
+ "The latter enables you to share your files with Windows(R) "
+ "computers on your network.</p>");
+}
+
+void KFileShareConfig::addShareBtnClicked() {
+ showShareDialog(KFileItemList());
+}
+
+
+PropertiesPageDlg::PropertiesPageDlg(QWidget*parent, KFileItemList files)
+ : KDialogBase(parent, "sharedlg", true,
+ i18n("Share Folder"), Ok|Cancel, Ok, true)
+{
+ QVBox* vbox = makeVBoxMainWidget();
+
+ m_page = new PropertiesPage(vbox,files,true);
+}
+
+bool PropertiesPageDlg::hasChanged() {
+ return m_page->hasChanged();
+}
+
+void PropertiesPageDlg::slotOk() {
+ if (hasChanged()) {
+ if (!m_page->save())
+ return;
+ }
+
+ KDialogBase::slotOk();
+}
+
+
+
+void KFileShareConfig::showShareDialog(const KFileItemList & files) {
+ PropertiesPageDlg* dlg = new PropertiesPageDlg(this,files);
+ if (dlg->exec() == QDialog::Accepted) {
+ if ( dlg->hasChanged() ) {
+ updateShareListView();
+ }
+ }
+ delete dlg;
+}
+
+void KFileShareConfig::changeShareBtnClicked() {
+ KFileItemList files;
+ QPtrList<QListViewItem> items = m_ccgui->listView->selectedItems();
+
+ QListViewItem* item;
+ for ( item = items.first(); item; item = items.next() ) {
+ files.append(new KFileItem(KURL::fromPathOrURL(item->text(0)),"",0));
+ }
+
+ showShareDialog(files);
+}
+
+void KFileShareConfig::removeShareBtnClicked() {
+
+ QPtrList<QListViewItem> items = m_ccgui->listView->selectedItems();
+ QListViewItem *item;
+
+ bool nfs = false;
+ bool samba = false;
+
+ for ( item = items.first(); item; item = items.next() ) {
+
+ if (KNFSShare::instance()->isDirectoryShared(item->text(0)))
+ nfs = true;
+
+ if (KSambaShare::instance()->isDirectoryShared(item->text(0)))
+ samba = true;
+ }
+
+ NFSFile nfsFile(KNFSShare::instance()->exportsPath());
+ if (nfs) {
+ kdDebug(FILESHARE_DEBUG) << "KFileShareConfig::removeShareBtnClicked: nfs = true" << endl;
+ nfsFile.load();
+ for ( item = items.first(); item; item = items.next() ) {
+ nfsFile.removeEntryByPath(item->text(0));
+ }
+ }
+
+ SambaFile smbFile(KSambaShare::instance()->smbConfPath(),false);
+ if (samba) {
+ kdDebug(FILESHARE_DEBUG) << "KFileShareConfig::removeShareBtnClicked: samba = true" << endl;
+ smbFile.load();
+ for ( item = items.first(); item; item = items.next() ) {
+ smbFile.removeShareByPath(item->text(0));
+ }
+ }
+
+ PropertiesPage::save(&nfsFile, &smbFile, nfs,samba);
+
+ updateShareListView();
+}
+
+#include "fileshare.moc"
diff --git a/filesharing/simple/fileshare.desktop b/filesharing/simple/fileshare.desktop
new file mode 100644
index 00000000..6ed8dd8b
--- /dev/null
+++ b/filesharing/simple/fileshare.desktop
@@ -0,0 +1,169 @@
+[Desktop Entry]
+Exec=kcmshell fileshare
+Icon=share
+Type=Application
+
+X-KDE-ModuleType=Library
+X-KDE-Library=fileshare
+X-KDE-ParentApp=kcontrol
+X-KDE-RootOnly=true
+
+Name=File Sharing
+Name[be]=Публікацыя файлаў
+Name[bg]=Споделяне на файлове
+Name[bn]=ফাইল ভাগাভাগি
+Name[br]=Rannañ restroù
+Name[bs]=Dijeljenje datoteka
+Name[ca]=Compartició de fitxers
+Name[cs]=Sdílení souborů
+Name[cy]=Rhannu Ffeiliau
+Name[da]=Fildeling
+Name[de]=Dateifreigabe
+Name[el]=Κοινή χρήση αρχείων
+Name[eo]=Dosierkomunigado
+Name[es]=Compartir archivos
+Name[et]=Failijagamine
+Name[eu]=Fitxategi partekatzea
+Name[fa]=اشتراک پرونده
+Name[fi]=Tiedostojen jakaminen
+Name[fr]=Partage de fichiers
+Name[ga]=Roinnt na gComhad
+Name[gl]=Compartición de ficheiros
+Name[he]=שיתוף קבצים
+Name[hu]=Fájlmegosztás
+Name[is]=Deila skrám
+Name[it]=Condivisione di file
+Name[ja]=ファイル共有
+Name[ka]=ფაილთა გაზიარება
+Name[kk]=Файлдарды ортақтастыру
+Name[km]=ការ​ចែក​រំលែក​ឯកសារ
+Name[lt]=Dalinimasis bylomis
+Name[mk]=Делење на датотеки
+Name[nb]=Fildeling
+Name[nds]=Dateifreegaav
+Name[ne]=फाइल साझेदारी
+Name[nl]=Bestanden delen
+Name[nn]=Fildeling
+Name[pa]=ਫਾਇਲ ਸ਼ਾਂਝ
+Name[pl]=Współdzielenie plików
+Name[pt]=Partilha de Ficheiros
+Name[pt_BR]=Compartilhamento de Arquivos
+Name[ro]=Partajare fişiere
+Name[ru]=Совместное использование файлов
+Name[se]=Fiilajuohkkin
+Name[sk]=Zdieľanie súborov
+Name[sl]=Souporaba datotek
+Name[sr]=Дељење фајлова
+Name[sr@Latn]=Deljenje fajlova
+Name[sv]=Filutdelning
+Name[ta]=கோப்பு பகிர்வு
+Name[tg]=Истифодабарии муштараки файлҳо
+Name[tr]=Dosya Paylaşımı
+Name[uk]=Спільний доступ до файлів
+Name[uz]=Fayl bilan boʻlishish
+Name[uz@cyrillic]=Файл билан бўлишиш
+Name[zh_CN]=文件共享
+Name[zh_HK]=檔案分享
+Name[zh_TW]=檔案分享
+
+Comment=Enable or disable file sharing
+Comment[be]=Уключыць/выключыць выкарыстанне агульных рэсурсаў
+Comment[bg]=Настройване споделянето на файлове
+Comment[bn]=ফাইল ভাগাভাগি সক্রিয় অথবা নিষ্ক্রিয় করুন
+Comment[bs]=Uključi ili isključi dijeljenje datoteka
+Comment[ca]=Habilita o deshabilita la compartició de fitxers
+Comment[cs]=Povolit nebo zakázat sdílení souborů
+Comment[da]=Aktivér eller deaktivér fildeling
+Comment[de]=Dateifreigabe aktivieren/deaktivieren
+Comment[el]=Ενεργοποίηση ή απενεργοποίηση της κοινής χρήσης αρχείων
+Comment[eo]=Ŝalti aŭ malŝalti dosierkomunigadon
+Comment[es]=Habilitar o deshabilitar el compartir archivos
+Comment[et]=Failide jagamise lubamine või keelamine
+Comment[eu]=Gaitu edo ezgaitu fitxategi partekatzea
+Comment[fa]=فعال یا غیرفعال‌سازی اشتراک پرونده
+Comment[fi]=Ota tiedostojen jakaminen käyttöön tai pois käytöstä
+Comment[fr]=Activer ou désactiver le partage de fichiers
+Comment[gl]=Habilitar ou deshabilitar a compartición de fichieros
+Comment[he]=אפשר או מנע שיתוף קבצים
+Comment[hu]=A fájlmegosztás ki-be kapcsolása
+Comment[is]=Virkja eða slökkva á skráardeilingu um net
+Comment[it]=Abilita o disabilita la condivisione dei file
+Comment[ja]=ファイル共有を有効または無効にします
+Comment[ka]=ფაილთა გაზიარების ჩართვა ან გამორთვა
+Comment[kk]=Файл ортақтастыруды рұқсат ету/етпеу
+Comment[km]=អនុញ្ញាត ឬ មិន​អនុញ្ញាត​ការ​ចែក​រំ​លែក​ឯកសារ
+Comment[lt]=Įjungti ar išjungti bylų dalinimąsi
+Comment[mk]=Овозможува или оневозможува делење на датотеки
+Comment[nb]=Slå på og av fildeling
+Comment[nds]=Dateifreegaven an- oder utmaken
+Comment[ne]=फाइल साझेदारी सक्षम वा अक्षम पार्नुहोस्
+Comment[nl]=Bestanden delen in- en uitschakelen
+Comment[nn]=Slå på eller av fildeling
+Comment[pl]=Włącza lub wyłącza współdzielenie plików
+Comment[pt]=Activa ou desactiva a partilha de ficheiros
+Comment[pt_BR]=Habilita ou desabilita o compartilhamento de arquivos
+Comment[ro]=Activează sau dezactivează partajarea de fişiere
+Comment[ru]=Включить или выключить общий доступ к файлам
+Comment[se]=Suova dahje ale suova fiilajuohkkima
+Comment[sk]=Povolenie alebo zakázanie zdieľania súborov
+Comment[sl]=Omogoči ali onemogoči souporabo datotek
+Comment[sr]=Укључи или искључи дељење фајлова
+Comment[sr@Latn]=Uključi ili isključi deljenje fajlova
+Comment[sv]=Aktivera eller inaktivera filutdelning
+Comment[ta]=கோப்பு பகிர்வை செயல்படுத்து அல்லது செயல்நீக்கு
+Comment[tg]=Фаъол сохтан ё хомӯш кардани истифобадарии муштараки файлҳо
+Comment[tr]=Dosya paylaşımını etkinleştir/kapat
+Comment[uk]=Увімкнення або вимикання спільного доступу до файлів
+Comment[zh_CN]=启用或禁用文件共享
+Comment[zh_HK]=啟用或停用檔案分享
+Comment[zh_TW]=開啟或關閉檔案分享
+
+Keywords=Share
+Keywords[be]=Агульны рэсурс
+Keywords[bg]=настройки, локална, мрежа, споделяне, share
+Keywords[br]=Rannañ
+Keywords[bs]=dijeljenje
+Keywords[ca]=Compartit
+Keywords[cs]=sdílení
+Keywords[da]=Del
+Keywords[de]=Freigabe
+Keywords[el]=Κοινόχρηστο
+Keywords[eo]=Komunaĵo
+Keywords[es]=Compartir
+Keywords[et]=Jagamine
+Keywords[fa]=مشترک
+Keywords[fi]=Jakaminen,Jako
+Keywords[fr]=partage
+Keywords[gl]=Compartir
+Keywords[he]=שיתוף, share
+Keywords[hu]=Megosztás
+Keywords[is]=Deild
+Keywords[it]=Condivisione
+Keywords[ja]=共有
+Keywords[ka]=საზიარო
+Keywords[km]=ការ​ចែក​រំ​លែក
+Keywords[lt]=Share,dalinimasis,dalintis,pasidalinti
+Keywords[mk]=Делена
+Keywords[nb]=Dele
+Keywords[nds]=Delen,Freegaav,Freegaven
+Keywords[ne]=साझेदार
+Keywords[nl]=delen
+Keywords[nn]=deling
+Keywords[pa]=ਸਾਂਝ
+Keywords[pl]=współdzielenie,pliki
+Keywords[pt]=Partilhar
+Keywords[pt_BR]=compartilhamento de arquivos
+Keywords[ro]=partajare
+Keywords[ru]=Общий ресурс
+Keywords[sk]=zdieľaný disk,share
+Keywords[sl]=Souporaba
+Keywords[sr]=Share,дељење
+Keywords[sr@Latn]=Share,deljenje
+Keywords[sv]=Dela
+Keywords[ta]=பகிர்வு
+Keywords[tg]=Муштаракан доштан
+Keywords[tr]=Paylaş
+Keywords[uk]=Спільний ресурс
+Keywords[zh_CN]=Share,共享
+
+Categories=Qt;KDE;X-KDE-settings-network;Settings;
diff --git a/filesharing/simple/fileshare.h b/filesharing/simple/fileshare.h
new file mode 100644
index 00000000..120b93f6
--- /dev/null
+++ b/filesharing/simple/fileshare.h
@@ -0,0 +1,82 @@
+/*
+ Copyright (c) 2002 Laurent Montel <lmontel@mandrakesoft.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __fileshare_h__
+#define __fileshare_h__
+
+#include <kfileitem.h>
+
+#include "kcmodule.h"
+class QRadioButton;
+class QLabel;
+class QBoxLayout;
+class ControlCenterGUI;
+class QListViewItem;
+
+class KFileShareConfig : public KCModule
+{
+ Q_OBJECT
+
+ public:
+ KFileShareConfig(QWidget *parent, const char *name, const QStringList &);
+
+ virtual void load();
+ virtual void save();
+ virtual void defaults();
+ virtual QString quickHelp() const;
+
+ protected:
+ ControlCenterGUI* m_ccgui;
+ QString m_fileShareGroup;
+ bool m_restricted;
+ bool m_rootPassNeeded;
+ QString m_smbConf;
+ void showShareDialog(const KFileItemList & files);
+ bool addGroupAccessesToFile(const QString & file);
+ bool removeGroupAccessesFromFile(const QString & file);
+ bool setGroupAccesses();
+
+ protected slots:
+ void configChanged() { emit changed( true ); };
+ void updateShareListView();
+ void allowedUsersBtnClicked();
+
+ virtual void addShareBtnClicked();
+ virtual void changeShareBtnClicked();
+ virtual void removeShareBtnClicked();
+
+};
+
+class PropertiesPageDlg : public KDialogBase
+{
+Q_OBJECT
+public:
+ PropertiesPageDlg(QWidget * parent, KFileItemList files);
+ ~PropertiesPageDlg() {};
+ bool hasChanged();
+protected:
+ PropertiesPage* m_page;
+
+protected slots:
+ virtual void slotOk();
+
+};
+
+
+
+#endif
diff --git a/filesharing/simple/groupconfigdlg.cpp b/filesharing/simple/groupconfigdlg.cpp
new file mode 100644
index 00000000..4d62faa9
--- /dev/null
+++ b/filesharing/simple/groupconfigdlg.cpp
@@ -0,0 +1,418 @@
+/*
+ Copyright (c) 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+
+#include <qradiobutton.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qhbox.h>
+
+#include <klocale.h>
+#include <kuser.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <klistbox.h>
+#include <kprocess.h>
+#include <kpushbutton.h>
+#include <kcombobox.h>
+
+#include "groupconfiggui.h"
+#include "groupconfigdlg.h"
+
+
+static QString groupListToString(const QValueList<KUserGroup> & list);
+static QString prettyString(const KUser &user);
+static QString fromPrettyString(const QString & s);
+static void removeList(QValueList<KUser> & from, const QValueList<KUser> & that);
+static bool userMod(const QString & user, const QValueList<KUserGroup> & groups);
+
+
+
+GroupConfigDlg::GroupConfigDlg(QWidget * parent,
+ const QString & fileShareGroup, bool restricted,
+ bool rootPassNeeded, bool simpleSharing)
+ : KDialogBase(parent,"groupconfigdlg", true,
+ i18n("Allowed Users"), Ok|Cancel, Ok, true) ,
+ m_fileShareGroup(fileShareGroup),
+ m_restricted(restricted) ,
+ m_rootPassNeeded(rootPassNeeded),
+ m_simpleSharing(simpleSharing)
+
+{
+ initGUI();
+
+ setFileShareGroup(m_fileShareGroup);
+}
+
+GroupConfigDlg::~GroupConfigDlg() {
+}
+
+void GroupConfigDlg::initUsers() {
+ m_origUsers = m_fileShareGroup.users();
+ m_users = m_origUsers;
+}
+
+void GroupConfigDlg::initGUI() {
+ m_gui = new GroupConfigGUI(this);
+ setMainWidget(m_gui);
+ setFileShareGroup(m_fileShareGroup);
+
+ m_gui->allUsersRadio->setChecked(!m_restricted);
+ m_gui->groupUsersRadio->setChecked(m_restricted);
+ m_gui->writeAccessChk->setChecked(!m_rootPassNeeded);
+
+ connect( m_gui->addBtn, SIGNAL(clicked()),
+ this, SLOT(slotAddUser()));
+ connect( m_gui->removeBtn, SIGNAL(clicked()),
+ this, SLOT(slotRemoveUser()));
+ connect( m_gui->otherGroupBtn, SIGNAL(clicked()),
+ this, SLOT(slotChangeGroup()));
+
+ if (m_simpleSharing) {
+ // if simple sharing users never need the root password
+ m_gui->writeAccessChk->setDisabled(true);
+ }
+}
+
+void GroupConfigDlg::updateListBox() {
+ m_gui->listBox->clear();
+ QValueList<KUser>::iterator it;
+ for ( it = m_users.begin(); it != m_users.end(); ++it ) {
+ m_gui->listBox->insertItem(prettyString(*it));
+ kdDebug(5009) << "GroupConfigDlg::updateListBox: " << (*it).loginName() << endl;
+ }
+}
+
+QString prettyString(const KUser &user) {
+ return user.fullName()+" ("+user.loginName()+")";
+}
+
+QString fromPrettyString(const QString & s) {
+ // Jan Schaefer (jan)
+ // i j
+ int i = s.find('(');
+ int j = s.find(')');
+ QString loginName = s.mid(i+1,j-i-1);
+ return loginName;
+}
+
+bool GroupConfigDlg::restricted() {
+ return m_restricted;
+}
+
+void GroupConfigDlg::slotAddUser() {
+ QValueList<KUser> allUsers = KUser::allUsers();
+
+ removeList(allUsers,m_users);
+
+ if (allUsers.count()==0) {
+ KMessageBox::information(this,
+ i18n("All users are in the %1 group already.")
+ .arg(m_fileShareGroup.name()));
+ return;
+ }
+
+ QStringList stringList;
+
+ QValueList<KUser>::iterator it;
+ for ( it = allUsers.begin(); it != allUsers.end(); ++it ) {
+ QString s = (*it).fullName()+" ("+(*it).loginName()+")";
+ stringList.append(s);
+ }
+
+ stringList.sort();
+
+ bool ok;
+ QString userName = KInputDialog::getItem(
+ i18n("Select User"),
+ i18n("Select a user:"),
+ stringList,
+ 0,
+ false,
+ &ok);
+
+ if (!ok)
+ return;
+
+ QString loginName = fromPrettyString(userName);
+ KUser user(loginName);
+ m_users.append(KUser(loginName));
+ updateListBox();
+}
+
+void removeList(QValueList<KUser> & from, const QValueList<KUser> & that) {
+ QValueList<KUser>::ConstIterator it;
+ for ( it = that.begin(); it != that.end(); ++it ) {
+ from.remove(*it);
+ }
+
+}
+
+bool GroupConfigDlg::addUser(const KUser & user, const KUserGroup & group) {
+ QValueList<KUserGroup> groups = user.groups();
+ groups.append(group);
+ if (!userMod(user.loginName(),groups)) {
+ KMessageBox::sorry(this,i18n("Could not add user '%1' to group '%2'")
+ .arg(user.loginName()).arg(group.name()));
+ return false;
+ }
+ return true;
+}
+
+
+bool GroupConfigDlg::removeUser(const KUser & user, const KUserGroup & group) {
+ QValueList<KUserGroup> groups = user.groups();
+ groups.remove(group);
+ if (!userMod(user.loginName(),groups)) {
+ KMessageBox::sorry(this,i18n("Could not remove user '%1' from group '%2'")
+ .arg(user.loginName()).arg(group.name()));
+ return false;
+ }
+ return true;
+}
+
+bool GroupConfigDlg::rootPassNeeded() {
+ return m_rootPassNeeded;
+}
+
+void GroupConfigDlg::slotOk() {
+ m_restricted = m_gui->groupUsersRadio->isChecked();
+ m_rootPassNeeded = ! m_gui->writeAccessChk->isChecked();
+ if (m_restricted && !m_fileShareGroup.isValid()) {
+ KMessageBox::sorry(this,i18n("You have to choose a valid group."));
+ return;
+ }
+
+ QValueList<KUser> addedUsers = m_users;
+ removeList(addedUsers,m_origUsers);
+ QValueList<KUser> removedUsers = m_origUsers;
+ removeList(removedUsers,m_users);
+
+ QValueList<KUser>::ConstIterator it;
+ for ( it = addedUsers.begin(); it != addedUsers.end(); ++it ) {
+ addUser(*it, m_fileShareGroup);
+ }
+
+ for ( it = removedUsers.begin(); it != removedUsers.end(); ++it ) {
+ removeUser(*it, m_fileShareGroup);
+ }
+
+
+ KDialogBase::slotOk();
+}
+
+bool userMod(const QString & user, const QValueList<KUserGroup> & groups) {
+ KProcess proc;
+ proc << "usermod" << "-G" << groupListToString(groups) << user;
+ return proc.start(KProcess::Block) && proc.normalExit();
+}
+
+void GroupConfigDlg::slotRemoveUser() {
+ QListBoxItem* item = m_gui->listBox->selectedItem();
+ if (!item)
+ return;
+
+ QString loginName = fromPrettyString(item->text());
+ KUser user(loginName);
+ m_users.remove(KUser(loginName));
+ updateListBox();
+ m_gui->removeBtn->setEnabled(false);
+}
+
+QString groupListToString(const QValueList<KUserGroup> & list) {
+ QValueList<KUserGroup>::ConstIterator it;
+ QString result;
+
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ result+=(*it).name()+",";
+ }
+
+ // remove last ,
+ result.truncate(result.length()-1);
+ return result;
+}
+
+void GroupConfigDlg::slotChangeGroup() {
+ QValueList<KUserGroup> allGroups = KUserGroup::allGroups();
+
+ QStringList stringList;
+
+ QValueList<KUserGroup>::iterator it;
+ for ( it = allGroups.begin(); it != allGroups.end(); ++it ) {
+ QString s = (*it).name();
+ stringList.append(s);
+ }
+
+ stringList.sort();
+
+ KDialogBase* dlg = new KDialogBase(this,"groupconfigdlg", true,
+ i18n("Allowed Users"), Ok|Cancel, Ok, true);
+
+ QVBox* vbox = dlg->makeVBoxMainWidget();
+
+ QHBox* hbox = new QHBox(vbox);
+ QLabel* lbl = new QLabel(i18n("New file share group:"),hbox);
+ KComboBox* combo = new KComboBox(hbox);
+ combo->insertStringList(stringList);
+ combo->setEditable(true);
+ combo->setCurrentText(m_fileShareGroup.name());
+
+ QCheckBox* addChk = new QCheckBox(
+ i18n("Add users from the old file share group to the new one"),
+ vbox);
+
+ QCheckBox* removeUsersChk = new QCheckBox(
+ i18n("Remove users from old file share group"),
+ vbox);
+
+ QCheckBox* removeGroupChk = new QCheckBox(
+ i18n("Delete the old file share group"),
+ vbox);
+
+ if (dlg->exec() == QDialog::Accepted) {
+ QString groupName = combo->currentText();
+ if (groupName != m_fileShareGroup.name()) {
+ QString oldGroup = m_fileShareGroup.name();
+ if (allGroups.contains(KUserGroup(groupName)))
+ setFileShareGroup(KUserGroup(groupName));
+ else {
+ if (!createFileShareGroup(groupName)) {
+ delete dlg;
+ return;
+ }
+ }
+
+ if (removeGroupChk->isChecked())
+ deleteGroup(oldGroup);
+ else
+ if (removeUsersChk->isChecked())
+ emptyGroup(oldGroup);
+
+ if (addChk->isChecked()) {
+ addUsersToGroup(m_users,KUserGroup(groupName));
+ // reread the users
+ m_fileShareGroup = KUserGroup(groupName);
+ }
+
+
+ initUsers();
+ updateListBox();
+
+ }
+ }
+
+ delete dlg;
+
+}
+
+void GroupConfigDlg::setFileShareGroup(const KUserGroup & group) {
+ m_fileShareGroup = group;
+
+ if (m_fileShareGroup.isValid()) {
+ initUsers();
+ updateListBox();
+ m_gui->groupUsersRadio->setText(
+ i18n("Only users of the '%1' group are allowed to share folders")
+ .arg(m_fileShareGroup.name()));
+ m_gui->usersGrpBx->setTitle(i18n("Users of '%1' Group")
+ .arg(m_fileShareGroup.name()));
+ m_gui->otherGroupBtn->setText(i18n("Change Group..."));
+ m_gui->usersGrpBx->show();
+ } else {
+ m_gui->groupUsersRadio->setText(i18n("Only users of a certain group are allowed to share folders"));
+ m_gui->otherGroupBtn->setText(i18n("Choose Group..."));
+ m_gui->usersGrpBx->hide();
+ }
+
+
+
+}
+
+bool GroupConfigDlg::addUsersToGroup(QValueList<KUser> users,const KUserGroup & group) {
+ QValueList<KUser>::ConstIterator it;
+ bool result = true;
+ for ( it = users.begin(); it != users.end(); ++it ) {
+ if (!addUser(*it, group))
+ result = false;
+ }
+ return result;
+}
+
+bool GroupConfigDlg::emptyGroup(const QString & s) {
+ if (KMessageBox::No == KMessageBox::questionYesNo(this,
+ i18n("Do you really want to remove all users from group '%1'?").arg(s), QString::null, KStdGuiItem::del(), KStdGuiItem::cancel())) {
+ return false;
+ }
+
+ QValueList<KUser> allUsers = KUser::allUsers();
+ bool result = true;
+ KUserGroup group(s);
+ QValueList<KUser>::ConstIterator it;
+ for ( it = allUsers.begin(); it != allUsers.end(); ++it ) {
+ if (!removeUser(*it, group))
+ result = false;
+ }
+ return result;
+}
+
+bool GroupConfigDlg::deleteGroup(const QString & s) {
+ if (KMessageBox::No == KMessageBox::questionYesNo(this,
+ i18n("Do you really want to delete group '%1'?").arg(s), QString::null, KStdGuiItem::del(), KStdGuiItem::cancel())) {
+ return false;
+ }
+
+ KProcess proc;
+ proc << "groupdel" << s;
+ bool result = proc.start(KProcess::Block) && proc.normalExit();
+ if (!result) {
+ KMessageBox::sorry(this,i18n("Deleting group '%1' failed.").arg(s));
+ }
+
+ return result;
+}
+
+bool GroupConfigDlg::createFileShareGroup(const QString & s) {
+ if (s.isEmpty()) {
+ KMessageBox::sorry(this,i18n("Please choose a valid group."));
+ return false;
+ }
+
+ if (KMessageBox::No == KMessageBox::questionYesNo(this,
+ i18n("This group '%1' does not exist. Should it be created?").arg(s), QString::null, i18n("Create"), i18n("Do Not Create")))
+ return false;
+
+ //debug("CreateFileShareGroup: "+s);
+ KProcess proc;
+ proc << "groupadd" << s;
+ bool result = proc.start(KProcess::Block) && proc.normalExit();
+ if (!result) {
+ KMessageBox::sorry(this,i18n("Creation of group '%1' failed.").arg(s));
+ } else {
+ setFileShareGroup(KUserGroup(s));
+ }
+
+ return result;
+}
+
+
+#include "groupconfigdlg.moc"
diff --git a/filesharing/simple/groupconfigdlg.h b/filesharing/simple/groupconfigdlg.h
new file mode 100644
index 00000000..79df8664
--- /dev/null
+++ b/filesharing/simple/groupconfigdlg.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (c) 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef GROUPCONFIGDLG_H
+#define GROUPCONFIGDLG_H
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <kuser.h>
+
+class GroupConfigGUI;
+
+class GroupConfigDlg : public KDialogBase
+{
+Q_OBJECT
+public:
+ GroupConfigDlg(QWidget * parent, const QString & fileShareGroup, bool restricted,
+ bool rootPassNeeded, bool simpleSharing);
+ ~GroupConfigDlg();
+ KUserGroup fileShareGroup() { return m_fileShareGroup; }
+ bool restricted();
+ bool rootPassNeeded();
+protected:
+ GroupConfigGUI* m_gui;
+
+ void initGUI();
+ void initUsers();
+protected slots:
+ void slotAddUser();
+ void slotRemoveUser();
+ void slotChangeGroup();
+ void updateListBox();
+ virtual void slotOk();
+
+private:
+ bool createFileShareGroup(const QString & s);
+ bool deleteGroup(const QString & s);
+ bool emptyGroup(const QString & s);
+ bool addUser(const KUser & user, const KUserGroup & group);
+ bool removeUser(const KUser & user, const KUserGroup & group);
+ bool addUsersToGroup(QValueList<KUser> users,const KUserGroup & group);
+ void setFileShareGroup(const KUserGroup & group);
+
+ QValueList<KUser> m_origUsers;
+ QValueList<KUser> m_users;
+ KUserGroup m_fileShareGroup;
+ bool m_restricted;
+ bool m_rootPassNeeded;
+ bool m_simpleSharing;
+};
+
+#endif
diff --git a/filesharing/simple/groupconfiggui.ui b/filesharing/simple/groupconfiggui.ui
new file mode 100644
index 00000000..c12e1d2c
--- /dev/null
+++ b/filesharing/simple/groupconfiggui.ui
@@ -0,0 +1,200 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>GroupConfigGUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>GroupConfigGUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>521</width>
+ <height>371</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>allUsersRadio</cstring>
+ </property>
+ <property name="text">
+ <string>Allow all users to share folders</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>groupUsersRadio</cstring>
+ </property>
+ <property name="text">
+ <string>Only users of the '%1' group are allowed to share folders</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>usersGrpBx</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>Users of '%1' Group</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListBox" row="0" column="0" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>listBox</cstring>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>removeBtn</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Remove User</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>addBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Add User</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>writeAccessChk</cstring>
+ </property>
+ <property name="text">
+ <string>Group members can share folders without root password</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>180</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>otherGroupBtn</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Change Group...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>groupUsersRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>usersGrpBx</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>groupUsersRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>otherGroupBtn</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>listBox</sender>
+ <signal>selectionChanged(QListBoxItem*)</signal>
+ <receiver>GroupConfigGUI</receiver>
+ <slot>listBox_selectionChanged(QListBoxItem*)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">groupconfiggui.ui.h</include>
+</includes>
+<slots>
+ <slot>listBox_selectionChanged( QListBoxItem * i )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/filesharing/simple/groupconfiggui.ui.h b/filesharing/simple/groupconfiggui.ui.h
new file mode 100644
index 00000000..35e82f7f
--- /dev/null
+++ b/filesharing/simple/groupconfiggui.ui.h
@@ -0,0 +1,14 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void GroupConfigGUI::listBox_selectionChanged( QListBoxItem * i)
+{
+ removeBtn->setEnabled(i);
+}
diff --git a/filesharing/simple/krichtextlabel.cpp b/filesharing/simple/krichtextlabel.cpp
new file mode 100644
index 00000000..0157a8f0
--- /dev/null
+++ b/filesharing/simple/krichtextlabel.cpp
@@ -0,0 +1,112 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2005 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "krichtextlabel.h"
+
+#include <qtooltip.h>
+#include <qstylesheet.h>
+#include <qsimplerichtext.h>
+
+#include <kglobalsettings.h>
+
+static QString qrichtextify( const QString& text )
+{
+ if ( text.isEmpty() || text[0] == '<' )
+ return text;
+
+ QStringList lines = QStringList::split('\n', text);
+ for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it)
+ {
+ *it = QStyleSheet::convertFromPlainText( *it, QStyleSheetItem::WhiteSpaceNormal );
+ }
+
+ return lines.join(QString::null);
+}
+
+KRichTextLabel::KRichTextLabel( const QString &text , QWidget *parent, const char *name )
+ : QLabel ( parent, name ) {
+ m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5);
+ setAlignment( Qt::WordBreak );
+ setText(text);
+}
+
+KRichTextLabel::KRichTextLabel( QWidget *parent, const char *name )
+ : QLabel ( parent, name ) {
+ m_defaultWidth = QMIN(400, KGlobalSettings::desktopGeometry(this).width()*2/5);
+ setAlignment( Qt::WordBreak );
+}
+
+void KRichTextLabel::setDefaultWidth(int defaultWidth)
+{
+ m_defaultWidth = defaultWidth;
+ updateGeometry();
+}
+
+QSizePolicy KRichTextLabel::sizePolicy() const
+{
+ return QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum, false);
+}
+
+QSize KRichTextLabel::minimumSizeHint() const
+{
+ QString qt_text = qrichtextify( text() );
+ int pref_width = 0;
+ int pref_height = 0;
+ QSimpleRichText rt(qt_text, font());
+ pref_width = m_defaultWidth;
+ rt.setWidth(pref_width);
+ int used_width = rt.widthUsed();
+ if (used_width <= pref_width)
+ {
+ while(true)
+ {
+ int new_width = (used_width * 9) / 10;
+ rt.setWidth(new_width);
+ int new_height = rt.height();
+ if (new_height > pref_height)
+ break;
+ used_width = rt.widthUsed();
+ if (used_width > new_width)
+ break;
+ }
+ pref_width = used_width;
+ }
+ else
+ {
+ if (used_width > (pref_width *2))
+ pref_width = pref_width *2;
+ else
+ pref_width = used_width;
+ }
+
+ return QSize(pref_width, rt.height());
+}
+
+QSize KRichTextLabel::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+void KRichTextLabel::setText( const QString &text ) {
+ QLabel::setText(text);
+}
+
+void KRichTextLabel::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "krichtextlabel.moc"
diff --git a/filesharing/simple/krichtextlabel.h b/filesharing/simple/krichtextlabel.h
new file mode 100644
index 00000000..35087fac
--- /dev/null
+++ b/filesharing/simple/krichtextlabel.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2005 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef KRICHTEXTLABEL_H
+#define KRICHTEXTLABEL_H
+
+#include <qlabel.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A replacement for QLabel that supports richtext and proper layout management
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ */
+
+/*
+ * QLabel
+ */
+class KDEUI_EXPORT KRichTextLabel : public QLabel {
+ Q_OBJECT
+
+public:
+ /**
+ * Default constructor.
+ */
+ KRichTextLabel( QWidget *parent, const char *name = 0 );
+ KRichTextLabel( const QString &text, QWidget *parent, const char *name = 0 );
+
+ int defaultWidth() const { return m_defaultWidth; }
+ void setDefaultWidth(int defaultWidth);
+
+ virtual QSize minimumSizeHint() const;
+ virtual QSize sizeHint() const;
+ QSizePolicy sizePolicy() const;
+
+public slots:
+ void setText( const QString & );
+
+protected:
+ int m_defaultWidth;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KRichTextLabelPrivate;
+ KRichTextLabelPrivate *d;
+};
+
+#endif // KRICHTEXTLABEL_H