summaryrefslogtreecommitdiff
authorerik <erik>2007-01-26 20:30:32 (UTC)
committer erik <erik>2007-01-26 20:30:32 (UTC)
commitf77da1ae08512b02a3c50a124f823ed77e53dd64 (patch) (side-by-side diff)
treeac7e414aff95348e0bf2fba3f45b2a06a4eb4623
parent4688f98202f590ec6af6c2e66a49dd2f80536083 (diff)
downloadopie-f77da1ae08512b02a3c50a124f823ed77e53dd64.zip
opie-f77da1ae08512b02a3c50a124f823ed77e53dd64.tar.gz
opie-f77da1ae08512b02a3c50a124f823ed77e53dd64.tar.bz2
Both packageslave.cpp and textedit.cpp have instances of possibly exploitable
race conditions associated to files. The big deal is that it is quite typical to use strings of pathnames to track files. But because that does not leverage the filesystem would be attackers may be able to exploit time lags in uses of filesystem functions (like stat and chmod or open) to get files with suspect data into the files that the applications are working with. This commit closes that potential hole even though there are no known exploits. Better safe then sorry. There is no change in the behavior of the apps.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/apps/textedit/textedit.cpp45
-rw-r--r--core/launcher/packageslave.cpp48
2 files changed, 49 insertions, 44 deletions
diff --git a/core/apps/textedit/textedit.cpp b/core/apps/textedit/textedit.cpp
index 4bbc62b..1c81a55 100644
--- a/core/apps/textedit/textedit.cpp
+++ b/core/apps/textedit/textedit.cpp
@@ -1,1191 +1,1188 @@
/**********************************************************************
// textedit.cpp
** Copyright (C) 2000 Trolltech AS. All rights reserved.
**
** This file is part of Opie Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
**********************************************************************/
// changes added by L. J. Potter Sun 02-17-2002 21:31:31
#include "textedit.h"
#include "filePermissions.h"
/* OPIE */
#include <opie2/odebug.h>
#include <opie2/ofileselector.h>
#include <opie2/ofiledialog.h>
#include <opie2/ofontselector.h>
#include <opie2/oresource.h>
#include <qpe/config.h>
#include <qpe/qpeapplication.h>
/* QT */
#include <qmenubar.h>
#include <qtoolbar.h>
#include <qtextstream.h>
#include <qclipboard.h>
#include <qaction.h>
#include <qlineedit.h>
#include <qmessagebox.h>
#include <qlayout.h>
#include <qtimer.h>
#include <qdir.h>
/* STD */
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h> //getenv
using namespace Opie::Core;
using namespace Opie::Ui;
#if QT_VERSION < 0x030000
class QpeEditor : public QMultiLineEdit
{
public:
QpeEditor( QWidget *parent, const char * name = 0 )
: QMultiLineEdit( parent, name ) {
clearTableFlags();
setTableFlags( Tbl_vScrollBar | Tbl_autoHScrollBar );
}
void find( const QString &txt, bool caseSensitive,
bool backwards );
protected:
bool markIt;
int line1, line2, col1, col2;
void mousePressEvent( QMouseEvent * );
void mouseReleaseEvent( QMouseEvent * );
//public slots:
/*
signals:
void notFound();
void searchWrapped();
*/
private:
};
void QpeEditor::mousePressEvent( QMouseEvent *e ) {
switch(e->button()) {
case RightButton:
{ //rediculous workaround for qt popup menu
//and the hold right click mechanism
this->setSelection( line1, col1, line2, col2);
QMultiLineEdit::mousePressEvent( e );
markIt = false;
}
break;
default:
{
if(!markIt) {
int line, col;
this->getCursorPosition(&line, &col);
line1=line2=line;
col1=col2=col;
}
QMultiLineEdit::mousePressEvent( e );
}
break;
};
}
void QpeEditor::mouseReleaseEvent( QMouseEvent * ) {
if(this->hasMarkedText()) {
markIt = true;
this->getMarkedRegion( &line1, &col1, &line2, & col2 );
} else {
markIt = false;
}
}
void QpeEditor::find ( const QString &txt, bool caseSensitive,
bool backwards )
{
static bool wrap = false;
int line, col;
if ( wrap ) {
if ( !backwards )
line = col = 0;
wrap = false;
// emit searchWrapped();
} else {
getCursorPosition( &line, &col );
}
//ignore backwards for now....
if ( !backwards ) {
for ( ; ; ) {
if ( line >= numLines() ) {
wrap = true;
//emit notFound();
break;
}
int findCol = getString( line )->find( txt, col, caseSensitive );
if ( findCol >= 0 ) {
setCursorPosition( line, findCol, false );
col = findCol + txt.length();
setCursorPosition( line, col, true );
//found = true;
break;
}
line++;
col = 0;
}
}
}
#else
#error "Must make a QpeEditor that inherits QTextEdit"
#endif
static const int nfontsizes = 6;
static const int fontsize[nfontsizes] = {8,10,12,14,18,24};
TextEdit::TextEdit( QWidget *parent, const char *name, WFlags f )
: QMainWindow( parent, name, f ), bFromDocView( false )
{
doc = 0;
edited=false;
fromSetDocument=false;
setToolBarsMovable( false );
connect( qApp,SIGNAL( aboutToQuit()),SLOT( cleanUp()) );
channel = new QCopChannel( "QPE/Application/textedit", this );
connect( channel, SIGNAL(received(const QCString&,const QByteArray&)),
this, SLOT(receive(const QCString&,const QByteArray&)) );
setIcon( Opie::Core::OResource::loadPixmap( "textedit/TextEditor", Opie::Core::OResource::SmallIcon ) );
QToolBar *bar = new QToolBar( this );
bar->setHorizontalStretchable( true );
menu = bar;
QMenuBar *mb = new QMenuBar( bar );
QPopupMenu *file = new QPopupMenu( this );
QPopupMenu *edit = new QPopupMenu( this );
QPopupMenu *advancedMenu = new QPopupMenu(this);
font = new QPopupMenu( this );
bar = new QToolBar( this );
editBar = bar;
QAction *a = new QAction( tr( "New" ), Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( fileNew() ) );
// a->addTo( bar );
a->addTo( file );
a = new QAction( tr( "Open" ), Opie::Core::OResource::loadPixmap( "fileopen", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( fileOpen() ) );
a->addTo( bar );
a->addTo( file );
a = new QAction( tr( "Save" ), Opie::Core::OResource::loadPixmap( "save", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( save() ) );
file->insertSeparator();
a->addTo( bar );
a->addTo( file );
a = new QAction( tr( "Save As" ), Opie::Core::OResource::loadPixmap( "save", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( saveAs() ) );
a->addTo( file );
a = new QAction( tr( "Cut" ), Opie::Core::OResource::loadPixmap( "cut", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( editCut() ) );
a->addTo( editBar );
a->addTo( edit );
a = new QAction( tr( "Copy" ), Opie::Core::OResource::loadPixmap( "copy", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( editCopy() ) );
a->addTo( editBar );
a->addTo( edit );
a = new QAction( tr( "Paste" ), Opie::Core::OResource::loadPixmap( "paste", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( editPaste() ) );
a->addTo( editBar );
a->addTo( edit );
#ifndef QT_NO_CLIPBOARD
a = new QAction( tr( "Insert Time and Date" ), Opie::Core::OResource::loadPixmap( "paste", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( editPasteTimeDate() ) );
a->addTo( edit );
#endif
a = new QAction( tr( "Goto Line..." ), Opie::Core::OResource::loadPixmap( "find", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( gotoLine() ) );
edit->insertSeparator();
a->addTo( edit );
a = new QAction( tr( "Find..." ), Opie::Core::OResource::loadPixmap( "find", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( editFind() ) );
a->addTo( bar );
a->addTo( edit );
zin = new QAction( tr("Zoom in"), QString::null, 0, this, 0 );
connect( zin, SIGNAL( activated() ), this, SLOT( zoomIn() ) );
zin->addTo( font );
zout = new QAction( tr("Zoom out"), QString::null, 0, this, 0 );
connect( zout, SIGNAL( activated() ), this, SLOT( zoomOut() ) );
zout->addTo( font );
font->insertSeparator();
font->insertItem(tr("Font"), this, SLOT(changeFont()) );
font->insertSeparator();
font->insertItem(tr("Advanced Features"), advancedMenu);
QAction *wa = new QAction( tr("Wrap lines"),
QString::null, 0, this, 0 );
connect( wa, SIGNAL( toggled(bool) ),
this, SLOT( setWordWrap(bool) ) );
wa->setToggleAction(true);
wa->addTo( advancedMenu);
nStart = new QAction( tr("Start with new file"),
QString::null, 0, this, 0 );
connect( nStart, SIGNAL( toggled(bool) ),
this, SLOT( changeStartConfig(bool) ) );
nStart->setToggleAction(true);
nStart->addTo( advancedMenu );
nStart->setEnabled(false);
nAdvanced = new QAction( tr("Prompt on Exit"),
QString::null, 0, this, 0 );
connect( nAdvanced, SIGNAL( toggled(bool) ),
this, SLOT( doPrompt(bool) ) );
nAdvanced->setToggleAction(true);
nAdvanced->addTo( advancedMenu );
desktopAction = new QAction( tr("Always open linked file"),
QString::null, 0, this, 0 );
connect( desktopAction, SIGNAL( toggled(bool) ),
this, SLOT( doDesktop(bool) ) );
desktopAction->setToggleAction(true);
desktopAction->addTo( advancedMenu);
filePermAction = new QAction( tr("File Permissions"),
QString::null, 0, this, 0 );
connect( filePermAction, SIGNAL( toggled(bool) ),
this, SLOT( doFilePerms(bool) ) );
filePermAction->setToggleAction(true);
filePermAction->addTo( advancedMenu);
searchBarAction = new QAction( tr("Search Bar Open"),
QString::null, 0, this, 0 );
connect( searchBarAction, SIGNAL( toggled(bool) ),
this, SLOT( setSearchBar(bool) ) );
searchBarAction->setToggleAction(true);
searchBarAction->addTo( advancedMenu);
nAutoSave = new QAction( tr("Auto Save 5 min."),
QString::null, 0, this, 0 );
connect( nAutoSave, SIGNAL( toggled(bool) ),
this, SLOT( doTimer(bool) ) );
nAutoSave->setToggleAction(true);
nAutoSave->addTo( advancedMenu);
//font->insertSeparator();
//font->insertItem(tr("About"), this, SLOT( doAbout()) );
mb->insertItem( tr( "File" ), file );
mb->insertItem( tr( "Edit" ), edit );
mb->insertItem( tr( "View" ), font );
searchBar = new QToolBar(this);
addToolBar( searchBar, "Search", QMainWindow::Top, true );
searchBar->setHorizontalStretchable( true );
searchEdit = new QLineEdit( searchBar, "searchEdit" );
searchBar->setStretchableWidget( searchEdit );
connect( searchEdit, SIGNAL( textChanged(const QString&) ),
this, SLOT( search() ) );
a = new QAction( tr( "Find Next" ), Opie::Core::OResource::loadPixmap( "next", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( findNext() ) );
a->addTo( searchBar );
a->addTo( edit );
a = new QAction( tr( "Close Find" ), Opie::Core::OResource::loadPixmap( "close", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( findClose() ) );
a->addTo( searchBar );
edit->insertSeparator();
a = new QAction( tr( "Delete" ), Opie::Core::OResource::loadPixmap( "close", Opie::Core::OResource::SmallIcon ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), this, SLOT( editDelete() ) );
a->addTo( edit );
searchBar->hide();
editor = new QpeEditor( this );
setCentralWidget( editor );
editor->setFrameStyle( QFrame::Panel | QFrame::Sunken );
connect( editor, SIGNAL( textChanged() ),
this, SLOT( editorChanged() ) );
QPEApplication::setStylusOperation( editor, QPEApplication::RightOnHold);
Config cfg("TextEdit");
cfg. setGroup ( "Font" );
QFont defaultFont = editor-> font ( );
QString family = cfg. readEntry ( "Family", defaultFont. family ( ));
int size = cfg. readNumEntry ( "Size", defaultFont. pointSize ( ));
int weight = cfg. readNumEntry ( "Weight", defaultFont. weight ( ));
bool italic = cfg. readBoolEntry ( "Italic", defaultFont. italic ( ));
defaultFont = QFont ( family, size, weight, italic );
editor-> setFont ( defaultFont );
// updateCaption();
cfg.setGroup ( "View" );
promptExit = cfg.readBoolEntry ( "PromptExit", false );
openDesktop = cfg.readBoolEntry ( "OpenDesktop", true );
filePerms = cfg.readBoolEntry ( "FilePermissions", false );
useSearchBar = cfg.readBoolEntry ( "SearchBar", false );
startWithNew = cfg.readBoolEntry ( "startNew", true);
featureAutoSave = cfg.readBoolEntry( "autosave", false);
if(useSearchBar) searchBarAction->setOn(true);
if(promptExit) nAdvanced->setOn( true );
if(openDesktop) desktopAction->setOn( true );
if(filePerms) filePermAction->setOn( true );
if(startWithNew) nStart->setOn( true );
if(featureAutoSave) nAutoSave->setOn(true);
// {
// doTimer(true);
// }
bool wrap = cfg. readBoolEntry ( "Wrap", true );
wa-> setOn ( wrap );
setWordWrap ( wrap );
/////////////////
if( qApp->argc() > 1) {
currentFileName=qApp->argv()[1];
QFileInfo fi(currentFileName);
if(fi.baseName().left(1) == "") {
openDotFile(currentFileName);
} else {
openFile(currentFileName);
}
} else {
edited1=false;
openDotFile("");
}
viewSelection = cfg.readNumEntry( "FileView", 0 );
}
TextEdit::~TextEdit() {
if( edited1 && !promptExit) {
switch( savePrompt() ) {
case 1: {
saveAs();
}
break;
};
}
delete editor;
}
void TextEdit::closeEvent(QCloseEvent *) {
if( promptExit) {
switch( savePrompt() ) {
case 1: {
saveAs();
qApp->quit();
}
break;
case 2: {
qApp->quit();
}
break;
case -1:
break;
};
}
else
qApp->quit();
}
void TextEdit::cleanUp() {
Config cfg ( "TextEdit" );
cfg. setGroup ( "Font" );
QFont f = editor->font();
cfg.writeEntry ( "Family", f. family ( ));
cfg.writeEntry ( "Size", f. pointSize ( ));
cfg.writeEntry ( "Weight", f. weight ( ));
cfg.writeEntry ( "Italic", f. italic ( ));
cfg.setGroup ( "View" );
cfg.writeEntry ( "Wrap", editor->wordWrap() == QMultiLineEdit::WidgetWidth );
cfg.writeEntry ( "FileView", viewSelection );
cfg.writeEntry ( "PromptExit", promptExit );
cfg.writeEntry ( "OpenDesktop", openDesktop );
cfg.writeEntry ( "FilePermissions", filePerms );
cfg.writeEntry ( "SearchBar", useSearchBar );
cfg.writeEntry ( "startNew", startWithNew );
}
void TextEdit::accept() {
if( edited1)
saveAs();
qApp->quit();
}
void TextEdit::zoomIn() {
setFontSize(editor->font().pointSize()+1,false);
}
void TextEdit::zoomOut() {
setFontSize(editor->font().pointSize()-1,true);
}
void TextEdit::setFontSize(int sz, bool round_down_not_up) {
int s=10;
for (int i=0; i<nfontsizes; i++) {
if ( fontsize[i] == sz ) {
s = sz;
break;
} else if ( round_down_not_up ) {
if ( fontsize[i] < sz )
s = fontsize[i];
} else {
if ( fontsize[i] > sz ) {
s = fontsize[i];
break;
}
}
}
QFont f = editor->font();
f.setPointSize(s);
editor->setFont(f);
zin->setEnabled(s != fontsize[nfontsizes-1]);
zout->setEnabled(s != fontsize[0]);
}
void TextEdit::setBold(bool y) {
QFont f = editor->font();
f.setBold(y);
editor->setFont(f);
}
void TextEdit::setItalic(bool y) {
QFont f = editor->font();
f.setItalic(y);
editor->setFont(f);
}
void TextEdit::setWordWrap(bool y) {
bool state = editor->edited();
QString captionStr = caption();
bool b1 = edited1;
bool b2 = edited;
editor->setWordWrap(y ? QMultiLineEdit::WidgetWidth : QMultiLineEdit::NoWrap );
editor->setEdited( state );
edited1=b1;
edited=b2;
setCaption(captionStr);
}
void TextEdit::setSearchBar(bool b) {
useSearchBar=b;
Config cfg("TextEdit");
cfg.setGroup("View");
cfg.writeEntry ( "SearchBar", b );
searchBarAction->setOn(b);
if(b)
searchBar->show();
else
searchBar->hide();
editor->setFocus();
}
void TextEdit::fileNew() {
// if( !bFromDocView ) {
// saveAs();
// }
newFile(DocLnk());
}
void TextEdit::fileOpen() {
Config cfg("TextEdit");
cfg. setGroup ( "View" );
QMap<QString, QStringList> map;
map.insert(tr("All"), QStringList() );
QStringList text;
text << "text/*";
map.insert(tr("Text"), text );
text << "*";
map.insert(tr("All"), text );
QString str = OFileDialog::getOpenFileName( 2,
QString::null ,
QString::null, map);
if( !str.isEmpty() && QFile(str).exists() && !QFileInfo(str).isDir() )
{
openFile( str );
}
else
updateCaption();
}
void TextEdit::doSearchBar() {
if(!useSearchBar)
searchBar->hide();
else
searchBar->show();
}
#if 0
void TextEdit::slotFind() {
FindDialog frmFind( tr("Text Editor"), this );
connect( &frmFind, SIGNAL(signalFindClicked(const QString&,bool,bool,int)),
editor, SLOT(slotDoFind(const QString&,bool,bool)));
//case sensitive, backwards, [category]
connect( editor, SIGNAL(notFound()),
&frmFind, SLOT(slotNotFound()) );
connect( editor, SIGNAL(searchWrapped()),
&frmFind, SLOT(slotWrapAround()) );
frmFind.exec();
}
#endif
void TextEdit::fileRevert() {
clear();
fileOpen();
}
void TextEdit::editCut() {
#ifndef QT_NO_CLIPBOARD
editor->cut();
#endif
}
void TextEdit::editCopy() {
#ifndef QT_NO_CLIPBOARD
editor->copy();
#endif
}
void TextEdit::editPaste() {
#ifndef QT_NO_CLIPBOARD
editor->paste();
#endif
}
void TextEdit::editFind() {
searchBar->show();
searchEdit->setFocus();
}
void TextEdit::findNext() {
editor->find( searchEdit->text(), false, false );
}
void TextEdit::findClose() {
searchBar->hide();
}
void TextEdit::search() {
editor->find( searchEdit->text(), false, false );
}
void TextEdit::newFile( const DocLnk &f ) {
DocLnk nf = f;
nf.setType("text/plain");
clear();
setWState (WState_Reserved1 );
editor->setFocus();
doc = new DocLnk(nf);
currentFileName = "Unnamed";
odebug << "newFile "+currentFileName << oendl;
updateCaption( currentFileName);
// editor->setEdited( false);
}
void TextEdit::openDotFile( const QString &f ) {
if(!currentFileName.isEmpty()) {
currentFileName=f;
odebug << "openFile dotfile " + currentFileName << oendl;
QString txt;
QFile file(f);
if (!file.open(IO_ReadWrite))
owarn << "Failed to open file " << file.name() << oendl;
else {
QTextStream t(&file);
while ( !t.atEnd()) {
txt+=t.readLine()+"\n";
}
editor->setText(txt);
editor->setEdited( false);
edited1=false;
edited=false;
}
}
updateCaption( currentFileName);
}
void TextEdit::openFile( const QString &f ) {
odebug << "filename is "+ f << oendl;
QString filer;
QFileInfo fi( f);
// bFromDocView = true;
if(f.find(".desktop",0,true) != -1 && !openDesktop )
{
switch ( QMessageBox::warning(this,tr("Text Editor"),tr("Text Editor has detected<BR>you selected a <B>.desktop</B>file.<BR>Open<B>.desktop</B> file or <B>linked</B> file?"),tr(".desktop File"),tr("Linked Document"),0,1,1) )
{
case 0: //desktop
filer = f;
break;
case 1: //linked
DocLnk sf(f);
filer = sf.file();
break;
};
}
else if(fi.baseName().left(1) == "")
{
odebug << "opening dotfile" << oendl;
currentFileName=f;
openDotFile(currentFileName);
return;
}
/*
* The problem is a file where Config(f).isValid() and it does not
* end with .desktop will be treated as desktop file
*/
else if (f.find(".desktop",0,true) != -1 )
{
DocLnk sf(f);
filer = sf.file();
if(filer.right(1) == "/")
filer = f;
}
else
filer = f;
DocLnk nf;
nf.setType("text/plain");
nf.setFile(filer);
currentFileName=filer;
nf.setName(fi.baseName());
openFile(nf);
odebug << "openFile string "+currentFileName << oendl;
showEditTools();
// Show filename in caption
QString name = filer;
int sep = name.findRev( '/' );
if ( sep > 0 )
name = name.mid( sep+1 );
updateCaption( name );
}
void TextEdit::openFile( const DocLnk &f ) {
// clear();
// bFromDocView = true;
FileManager fm;
QString txt;
currentFileName=f.file();
odebug << "openFile doclnk " + currentFileName << oendl;
if ( !fm.loadFile( f, txt ) ) {
// ####### could be a new file
odebug << "Cannot open file" << oendl;
}
// fileNew();
if ( doc )
delete doc;
doc = new DocLnk(f);
editor->setText(txt);
editor->setEdited( false);
edited1=false;
edited=false;
doc->setName(currentFileName);
updateCaption();
setTimer();
}
void TextEdit::showEditTools() {
menu->show();
editBar->show();
if(!useSearchBar)
searchBar->hide();
else
searchBar->show();
setWState (WState_Reserved1 );
}
/*!
unprompted save */
bool TextEdit::save() {
- QString name, file;
+ QString name, file;
odebug << "saveAsFile " + currentFileName << oendl;
if(currentFileName.isEmpty()) {
saveAs();
return false;
}
- name = currentFileName;
- if(doc) {
- file = doc->file();
- odebug << "saver file "+file << oendl;
- name = doc->name();
- odebug << "File named "+name << oendl;
- } else {
- file = currentFileName;
+ if(doc) {
+ file = doc->file();
+ odebug << "saver file "+file << oendl;
+ name = doc->name();
+ odebug << "File named "+name << oendl;
+ } else {
+ file = currentFileName;
name = QFileInfo(currentFileName).baseName();
- }
+ }
QString rt = editor->text();
if( !rt.isEmpty() ) {
if(name.isEmpty()) {
saveAs();
} else {
currentFileName = name;
odebug << "saveFile "+currentFileName << oendl;
struct stat buf;
mode_t mode;
- stat(file.latin1(), &buf);
+ QFile f(file);
+ fstat(f.handle(), &buf);
mode = buf.st_mode;
if(!fileIs) {
doc->setName( name);
FileManager fm;
if ( !fm.saveFile( *doc, rt ) ) {
- QMessageBox::message(tr("Text Edit"),tr("Save Failed"));
+ QMessageBox::message(tr("Text Edit"),tr("Save Failed"));
return false;
}
} else {
odebug << "regular save file" << oendl;
- QFile f(file);
- if( f.open(IO_WriteOnly)) {
- QCString crt = rt.utf8();
- f.writeBlock(crt,crt.length());
- } else {
- QMessageBox::message(tr("Text Edit"),tr("Write Failed"));
- return false;
- }
-
+ if( f.open(IO_WriteOnly)) {
+ QCString crt = rt.utf8();
+ f.writeBlock(crt,crt.length());
+ } else {
+ QMessageBox::message(tr("Text Edit"),tr("Write Failed"));
+ return false;
+ }
}
editor->setEdited( false);
edited1=false;
edited=false;
if(caption().left(1)=="*")
- setCaption(caption().right(caption().length()-1));
-
+ setCaption(caption().right(caption().length()-1));
- chmod( file.latin1(), mode);
+ fchmod( f.handle(), mode);
}
return true;
}
return false;
}
/*!
prompted save */
bool TextEdit::saveAs() {
if(caption() == tr("Text Editor"))
return false;
odebug << "saveAsFile " + currentFileName << oendl;
QString rt = editor->text();
odebug << currentFileName << oendl;
if( currentFileName.isEmpty()
|| currentFileName == tr("Unnamed")
|| currentFileName == tr("Text Editor"))
{
odebug << "do silly TT filename thing" << oendl;
QString pt = rt.simplifyWhiteSpace();
int i = pt.find( ' ' );
QString docname = pt;
if ( i > 0 ) docname = pt.left( i );
while( docname.startsWith( "." ) )
docname = docname.mid( 1 );
docname.replace( QRegExp("/"), "_" );
// Cut the length. Filenames longer than 40 are not helpful
// and something goes wrong when they get too long.
if ( docname.length() > 40 ) docname = docname.left(40);
if ( docname.isEmpty() ) docname = tr("Unnamed");
if(doc) doc->setName(docname);
currentFileName=docname;
}
QMap<QString, QStringList> map;
map.insert(tr("All"), QStringList() );
QStringList text;
text << "text/*";
map.insert(tr("Text"), text );
text << "*";
map.insert(tr("All"), text );
QFileInfo cuFi( currentFileName);
QString filee = cuFi.fileName();
QString dire = cuFi.dirPath();
if(dire==".")
dire = QPEApplication::documentDir();
QString str;
if( !featureAutoSave) {
str = OFileDialog::getSaveFileName( 2, dire, filee, map);
} else
str = currentFileName;
if(!str.isEmpty()) {
QString fileNm=str;
odebug << "saving filename "+fileNm << oendl;
QFileInfo fi(fileNm);
currentFileName=fi.fileName();
if(doc)
delete doc;
DocLnk nf;
nf.setType("text/plain");
nf.setFile( fileNm);
doc = new DocLnk(nf);
odebug << "Saving file as "+currentFileName << oendl;
doc->setName( fi.baseName() );
updateCaption( currentFileName);
FileManager fm;
if ( !fm.saveFile( *doc, rt ) ) {
QMessageBox::message(tr("Text Edit"),tr("Save Failed"));
return false;
}
if( filePerms ) {
filePermissions *filePerm;
filePerm = new filePermissions(this, tr("Permissions"),true, 0,
(const QString &)fileNm);
QPEApplication::execDialog( filePerm );
delete filePerm;
}
editor->setEdited( false);
edited1 = false;
edited = false;
if(caption().left(1)=="*")
setCaption(caption().right(caption().length()-1));
return true;
}
odebug << "returning false" << oendl;
currentFileName = "";
return false;
} //end saveAs
void TextEdit::clear() {
delete doc;
doc = 0;
editor->clear();
}
void TextEdit::updateCaption( const QString &name ) {
if ( name.isEmpty() )
setCaption( tr("Text Editor") );
else {
QString s = name;
if ( s.isNull() )
s = doc->name();
if ( s.isEmpty() ) {
s = tr( "Unnamed" );
currentFileName=s;
}
// if(s.left(1) == "/")
// s = s.right(s.length()-1);
setCaption( tr("%1 - Text Editor").arg( s ) );
}
}
void TextEdit::setDocument(const QString& fileref) {
if(fileref != "Unnamed") {
currentFileName=fileref;
odebug << "setDocument" << oendl;
QFileInfo fi(currentFileName);
odebug << "basename:"+fi.baseName()+": current filenmame "+currentFileName << oendl;
if( (fi.baseName().left(1)).isEmpty() ) {
openDotFile(currentFileName);
} else {
odebug << "setDoc open" << oendl;
bFromDocView = true;
openFile(fileref);
editor->setEdited(true);
edited1=false;
edited=true;
// fromSetDocument=false;
// doSearchBar();
}
}
updateCaption( currentFileName);
}
void TextEdit::changeFont() {
QDialog *d = new QDialog ( this, "FontDialog", true );
d-> setCaption ( tr( "Choose font" ));
QBoxLayout *lay = new QVBoxLayout ( d );
OFontSelector *ofs = new OFontSelector ( true, d );
lay-> addWidget ( ofs );
ofs-> setSelectedFont ( editor-> font ( ));
if ( QPEApplication::execDialog( d ) == QDialog::Accepted )
editor-> setFont ( ofs-> selectedFont ( ));
delete d;
}
void TextEdit::editDelete() {
switch ( QMessageBox::warning(this,tr("Text Editor"),
tr("Do you really want<BR>to <B>delete</B> "
"the current file\nfrom the disk?<BR>This is "
"<B>irreversable!</B>"),
tr("Yes"),tr("No"),0,0,1) ) {
case 0:
if(doc) {
doc->removeFiles();
clear();
setCaption( tr("Text Editor") );
}
break;
case 1:
// exit
break;
};
}
void TextEdit::changeStartConfig( bool b ) {
startWithNew=b;
Config cfg("TextEdit");
cfg.setGroup("View");
cfg.writeEntry("startNew",b);
update();
}
void TextEdit::editorChanged() {
// odebug << "editor changed" << oendl;
if( /*editor->edited() &&*/ /*edited && */!edited1) {
setCaption( "*"+caption());
edited1=true;
}
edited=true;
}
void TextEdit::receive(const QCString&msg, const QByteArray &) {
odebug << "QCop "+msg << oendl;
if ( msg == "setDocument(QString)" ) {
odebug << "bugger all" << oendl;
}
}
void TextEdit::doAbout() {
QMessageBox::about(0,tr("Text Edit"),tr("Text Edit is copyright<BR>"
"2000 Trolltech AS, and<BR>"
"2002 by <B>L. J. Potter <BR>llornkcor@handhelds.org</B><BR>"
"and is licensed under the GPL"));
}
void TextEdit::doPrompt(bool b) {
promptExit=b;
Config cfg("TextEdit");
cfg.setGroup ( "View" );
cfg.writeEntry ( "PromptExit", b);
}
void TextEdit::doDesktop(bool b) {
openDesktop=b;
Config cfg("TextEdit");
cfg.setGroup ( "View" );
cfg.writeEntry ( "OpenDesktop", b);
}
void TextEdit::doFilePerms(bool b) {
filePerms=b;
Config cfg("TextEdit");
cfg.setGroup ( "View" );
cfg.writeEntry ( "FilePermissions", b);
}
void TextEdit::editPasteTimeDate() {
#ifndef QT_NO_CLIPBOARD
QClipboard *cb = QApplication::clipboard();
QDateTime dt = QDateTime::currentDateTime();
cb->setText( dt.toString());
editor->paste();
#endif
}
int TextEdit::savePrompt()
{
switch( QMessageBox::information( 0, (tr("Textedit")),
(tr("Textedit detected\n"
"you have unsaved changes\n"
"Go ahead and save?\n")),
(tr("Save")), (tr("Don't Save")), (tr("&Cancel")), 2, 2 ) )
{
case 0:
{
return 1;
}
break;
case 1:
{
return 2;
}
break;
case 2:
{
return -1;
}
break;
};
return 0;
}
void TextEdit::timerCrank()
{
if(featureAutoSave && edited1)
{
if(currentFileName.isEmpty())
{
currentFileName = QDir::homeDirPath()+"/textedit.tmp";
saveAs();
}
else
{
// odebug << "autosave" << oendl;
save();
}
setTimer();
}
}
void TextEdit::doTimer(bool b)
{
Config cfg("TextEdit");
cfg.setGroup ( "View" );
cfg.writeEntry ( "autosave", b);
featureAutoSave = b;
nAutoSave->setOn(b);
if(b)
{
// odebug << "doTimer true" << oendl;
setTimer();
}
// else
// odebug << "doTimer false" << oendl;
}
void TextEdit::setTimer()
{
if(featureAutoSave)
{
// odebug << "setting autosave" << oendl;
QTimer *timer = new QTimer(this );
connect( timer, SIGNAL(timeout()), this, SLOT(timerCrank()) );
timer->start( 300000, true); //5 minutes
}
}
void TextEdit::gotoLine() {
if( editor->length() < 1)
return;
QWidget *d = QApplication::desktop();
gotoEdit = new QLineEdit( 0, "Goto line");
gotoEdit->move( (d->width()/2) - ( gotoEdit->width()/2) , (d->height()/2) - (gotoEdit->height()/2));
gotoEdit->setFrame(true);
gotoEdit->show();
connect (gotoEdit,SIGNAL(returnPressed()), this, SLOT(doGoto()));
}
void TextEdit::doGoto() {
QString number = gotoEdit->text();
gotoEdit->hide();
delete gotoEdit;
gotoEdit = 0;
bool ok;
int lineNumber = number.toInt(&ok, 10);
if( editor->numLines() < lineNumber)
QMessageBox::message(tr("Text Edit"),tr("Not enough lines"));
else
{
editor->setCursorPosition(lineNumber, 0, false);
}
}
diff --git a/core/launcher/packageslave.cpp b/core/launcher/packageslave.cpp
index abbc610..965020e 100644
--- a/core/launcher/packageslave.cpp
+++ b/core/launcher/packageslave.cpp
@@ -1,348 +1,356 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "packageslave.h"
/* OPIE */
#include <opie2/odebug.h>
#include <qtopia/qprocess.h>
#ifdef Q_WS_QWS
#include <qtopia/qcopenvelope_qws.h>
#endif
using namespace Opie::Core;
/* QT */
#ifdef Q_WS_QWS
#include <qcopchannel_qws.h>
#endif
#include <qtextstream.h>
/* STD */
#include <stdlib.h>
#include <sys/stat.h> // mkdir()
#if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
#include <unistd.h>
#include <sys/vfs.h>
#include <mntent.h>
#elif defined(Q_OS_MACX)
#include <unistd.h>
#endif
PackageHandler::PackageHandler( QObject *parent, char* name )
: QObject( parent, name ), packageChannel( 0 ), currentProcess( 0 ), mNoSpaceLeft( FALSE )
{
// setup qcop channel
#ifndef QT_NO_COP
packageChannel = new QCopChannel( "QPE/Package", this );
connect( packageChannel, SIGNAL( received(const QCString&,const QByteArray&) ),
this, SLOT( qcopMessage(const QCString&,const QByteArray&) ) );
#endif
}
void PackageHandler::qcopMessage( const QCString &msg, const QByteArray &data )
{
QDataStream stream( data, IO_ReadOnly );
if ( msg == "installPackage(QString)" ) {
QString file;
stream >> file;
installPackage( file );
} else if ( msg == "installPackage(QString,QString)" ) {
QString file, dest;
stream >> file >> dest;
installPackage( file, dest );
} else if ( msg == "removePackage(QString)" ) {
QString file;
stream >> file;
removePackage( file );
} else if ( msg == "addPackageFiles(QString,QString)" ) {
QString location, listfile;
stream >> location >> listfile;
addPackageFiles( location, listfile);
} else if ( msg == "addPackages(QString)" ) {
QString location;
stream >> location;
addPackages( location );
} else if ( msg == "cleanupPackageFiles(QString)" ) {
QString listfile;
stream >> listfile;
cleanupPackageFiles( listfile );
} else if ( msg == "cleanupPackages(QString)" ) {
QString location;
stream >> location;
cleanupPackages( location );
} else if ( msg == "prepareInstall(QString,QString)" ) {
QString size, path;
stream >> size;
stream >> path;
prepareInstall( size, path );
}
}
void PackageHandler::installPackage( const QString &package, const QString &dest )
{
if ( mNoSpaceLeft ) {
mNoSpaceLeft = FALSE;
// Don't emit that for now, I still couldn't test it (Wener)
//sendReply( "installFailed(QString)", package );
//return;
}
QStringList cmd;
cmd << "ipkg";
if ( !dest.isEmpty() ) {
cmd << "-d" << dest;
}
cmd << "install" << package;
currentProcess = new QProcess( cmd ); // No tr
connect( currentProcess, SIGNAL( processExited() ), SLOT( iProcessExited() ) );
connect( currentProcess, SIGNAL( readyReadStdout() ), SLOT( readyReadStdout() ) );
connect( currentProcess, SIGNAL( readyReadStderr() ), SLOT( readyReadStderr() ) );
currentPackage = package;
currentProcessError="";
sendReply( "installStarted(QString)", package );
currentProcess->start();
}
void PackageHandler::removePackage( const QString &package )
{
currentProcess = new QProcess( QStringList() << "ipkg" << "remove" << package ); // No tr
connect( currentProcess, SIGNAL( processExited() ), SLOT( rmProcessExited() ) );
connect( currentProcess, SIGNAL( readyReadStdout() ), SLOT( readyReadStdout() ) );
connect( currentProcess, SIGNAL( readyReadStderr() ), SLOT( readyReadStderr() ) );
currentPackage = package;
currentProcessError="";
sendReply( "removeStarted(QString)", package );
currentProcess->start();
}
void PackageHandler::sendReply( const QCString& msg, const QString& arg )
{
#ifndef QT_NO_COP
QCopEnvelope e( "QPE/Desktop", msg );
e << arg;
#endif
}
void PackageHandler::addPackageFiles( const QString &location,
const QString &listfile )
{
QFile f(listfile);
#ifndef Q_OS_WIN32
//make a copy so we can remove the symlinks later
mkdir( ("/usr/lib/ipkg/info/"+location).ascii(), 0777 );
system(("cp " + f.name() + " /usr/lib/ipkg/info/"+location).ascii());
#else
QDir d;
//#### revise
odebug << "Copy file at " << __FILE__ << ": " << __LINE__ << "" << oendl;
d.mkdir(("/usr/lib/ipkg/info/" + location).ascii());
system(("copy " + f.name() + " /usr/lib/ipkg/info/"+location).ascii());
#endif
if ( f.open(IO_ReadOnly) ) {
QTextStream ts(&f);
QString s;
while ( !ts.eof() ) { // until end of file...
s = ts.readLine(); // line of text excluding '\n'
// for s, do link/mkdir.
if ( s.right(1) == "/" ) {
odebug << "do mkdir for " << s.ascii() << "" << oendl;
#ifndef Q_OS_WIN32
mkdir( s.ascii(), 0777 );
//possible optimization: symlink directories
//that don't exist already. -- Risky.
#else
d.mkdir( s.ascii());
#endif
} else {
#ifndef Q_OS_WIN32
odebug << "do symlink for " << s.ascii() << "" << oendl;
symlink( (location + s).ascii(), s.ascii() );
#else
odebug << "Copy file instead of a symlink for WIN32" << oendl;
if (!CopyFile((TCHAR*)qt_winTchar((location + s), TRUE), (TCHAR*)qt_winTchar(s, TRUE), FALSE))
owarn << "Unable to create symlinkfor " << (location + s).ascii() << oendl;
#endif
}
}
f.close();
}
}
void PackageHandler::addPackages( const QString &location )
{
// get list of *.list in location/usr/lib/ipkg/info/*.list
QDir dir(location + "/usr/lib/ipkg/info", "*.list", // No tr
QDir::Name, QDir::Files);
if ( !dir.exists() )
return;
QStringList packages = dir.entryList();
for ( QStringList::Iterator it = packages.begin();
it != packages.end(); ++it ) {
addPackageFiles( location, *it );
}
}
void PackageHandler::cleanupPackageFiles( const QString &listfile )
{
QFile f(listfile);
if ( f.open(IO_ReadOnly) ) {
- QTextStream ts(&f);
-
- QString s;
- while ( !ts.eof() ) { // until end of file...
- s = ts.readLine(); // line of text excluding '\n'
- // for s, do link/mkdir.
- if ( s.right(1) == "/" ) {
- //should rmdir if empty, after all files have been removed
- } else {
+ QTextStream ts(&f);
+
+ QString s;
+ while ( !ts.eof() ) { // until end of file...
+ s = ts.readLine(); // line of text excluding '\n'
+ // for s, do link/mkdir.
+ // @todo Right now we just move on if the name of the file we
+ // find is actually a directory. What we ought to do is check
+ // to see if the directory is empty and if so remove it.
+ if ( s.right(1) != "/" ) {
#ifndef Q_OS_WIN32
- odebug << "remove symlink for " << s.ascii() << "" << oendl;
- //check if it is a symlink first (don't remove /etc/passwd...)
- char buf[10]; //we don't care about the contents
- if ( ::readlink( s.ascii(),buf, 10 >= 0 ) )
- ::unlink( s.ascii() );
+ odebug << "remove symlink for " << s << oendl;
+ QFile symFile(s);
+ QFileInfo symFileInfo(symFile);
+ //check if it is a symlink first (don't remove /etc/passwd...)
+ if ( !symFileInfo.readLink().isNull())
+ if (!symFile.remove())
+ owarn << "Unable to remove symlink " << symFile.name()
+ << " " << __FILE__ << ":" << __LINE__ << oendl;
#else
- // ### revise
- owarn << "Unable to remove symlink " << __FILE__ << ":" << __LINE__ << "" << oendl;
+ // @todo If we actually want to be portable to other operating
+ // systems we ought to at least have a portable way of removing
+ // their notion of symlinks.
+ owarn << "Unable to remove symlink " << s " " << __FILE__
+ << ":" << __LINE__ << oendl;
#endif
+ }
}
- }
- f.close();
+ f.close();
//remove the list file
- ::unlink( listfile.ascii() );
-
+ if (!f.remove())
+ owarn << "Unable to remove list file " << f.name() << " "
+ << __FILE__ << ":" << __LINE__ << oendl;
}
}
void PackageHandler::cleanupPackages( const QString &location )
{
// get list of *.list in location/usr/lib/ipkg/info/*.list
QDir dir( "/usr/lib/ipkg/info/"+location, "*.list", // No tr
QDir::Name, QDir::Files);
if ( !dir.exists() )
return;
QStringList packages = dir.entryList();
for ( QStringList::Iterator it = packages.begin();
it != packages.end(); ++it ) {
cleanupPackageFiles( *it );
}
//remove the backup directory
//###
}
void PackageHandler::prepareInstall( const QString& size, const QString& path )
{
// Check whether there will be enough space to install the next package.
bool ok;
unsigned int s = size.toUInt( &ok );
if ( !ok )
return;
// Shamelessly stolen from the sysinfo application (Werner)
#if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
struct statfs fs;
if ( statfs( path.latin1(), &fs ) == 0 )
if ( s > fs.f_bsize * fs.f_bavail ) {
//odebug << "############### Not enough space left ###############" << oendl;
mNoSpaceLeft = TRUE;
}
#endif
}
void PackageHandler::iProcessExited()
{
if ( currentProcess->normalExit() && currentProcess->exitStatus() == 0 )
sendReply( "installDone(QString)", currentPackage );
else {
#ifndef QT_NO_COP
QCopEnvelope e( "QPE/Desktop", "installFailed(QString,int,QString)" );
e << currentPackage << currentProcess->exitStatus()
<< currentProcessError;
#endif
}
delete currentProcess;
currentProcess = 0;
#ifndef QT_NO_COP
QCopEnvelope e("QPE/System", "linkChanged(QString)");
QString lf = QString::null;
e << lf;
#endif
unlink( currentPackage );
}
void PackageHandler::rmProcessExited()
{
if ( currentProcess->normalExit() && currentProcess->exitStatus() == 0 )
sendReply( "removeDone(QString)", currentPackage );
else
sendReply( "removeFailed(QString)", currentPackage );
#ifndef QT_NO_COP
QCopEnvelope e("QPE/System", "linkChanged(QString)");
QString lf = QString::null;
e << lf;
#endif
}
void PackageHandler::readyReadStdout()
{
while ( currentProcess->canReadLineStdout() ) {
QString line = currentProcess->readLineStdout();
currentProcessError.append("OUT:"+line);
if ( line.contains( "Unpacking" ) ) // No tr
sendReply( "installStep(QString)", "one" ); // No tr
else if ( line.contains( "Configuring" ) ) // No tr
sendReply( "installStep(QString)", "two" ); // No tr
}
}
void PackageHandler::readyReadStderr()
{
while ( currentProcess->canReadLineStderr() ) {
QString line = currentProcess->readLineStderr();
currentProcessError.append("ERR:"+line);
}
}
void PackageHandler::redoPackages()
{
//get list of filesystems
//call cleanupPackages for the ones that have disappeared
//call addPackageFiles for the new ones
}