00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <time.h>
00028 #include <stdlib.h>
00029 #include <zlib.h>
00030
00031 #include <QtCore/QDir>
00032 #include <QtCore/QString>
00033 #include <QtDBus/QtDBus>
00034
00035 #include <kcomponentdata.h>
00036 #include <klocale.h>
00037 #include <kcmdlineargs.h>
00038 #include <kglobal.h>
00039 #include <kstandarddirs.h>
00040 #include <kprotocolmanager.h>
00041
00042 #include <unistd.h>
00043
00044 #include <kdebug.h>
00045
00046 time_t currentDate;
00047 int m_maxCacheAge;
00048 int m_maxCacheSize;
00049
00050 static const char appFullName[] = "org.kde.kio_http_cache_cleaner";
00051 static const char appName[] = "kio_http_cache_cleaner";
00052
00053 static const char version[] = "1.0.0";
00054
00055 struct FileInfo {
00056 QString name;
00057 int size;
00058
00059 int rating;
00060
00061 bool operator<( const struct FileInfo &info )
00062 {
00063 return ( rating < info.rating);
00064 }
00065 };
00066
00067 template class QList<FileInfo*>;
00068
00069 class FileInfoList : public QList<FileInfo*>
00070 {
00071 public:
00072 FileInfoList() : QList<FileInfo*>() { }
00073 };
00074
00075
00076
00077 #define CACHE_REVISION "7\n"
00078
00079 FileInfo *readEntry( const QString &filename)
00080 {
00081 QByteArray CEF = QFile::encodeName(filename);
00082 gzFile fs = gzopen( CEF.data(), "r");
00083 if (!fs)
00084 return 0;
00085
00086 char buffer[401];
00087 bool ok = true;
00088
00089
00090 if (ok && (!gzgets(fs, buffer, 400)))
00091 ok = false;
00092 if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
00093 ok = false;
00094
00095
00096 if (ok && (!gzgets(fs, buffer, 400)))
00097 ok = false;
00098
00099 time_t creationDate;
00100 int age =0;
00101
00102
00103 if (ok && (!gzgets(fs, buffer, 400)))
00104 ok = false;
00105 if (ok)
00106 {
00107 creationDate = (time_t) strtoul(buffer, 0, 10);
00108 age = (int) difftime(currentDate, creationDate);
00109 if ( m_maxCacheAge && ( age > m_maxCacheAge))
00110 {
00111 ok = false;
00112 }
00113 }
00114
00115
00116 if (ok && (!gzgets(fs, buffer, 400)))
00117 ok = false;
00118 if (ok)
00119 {
00120
00121 #if 0
00122 time_t expireDate;
00123 expireDate = (time_t) strtoul(buffer, 0, 10);
00124 if (expireDate && (expireDate < currentDate))
00125 ok = false;
00126 #endif
00127 }
00128
00129
00130 if (ok && (!gzgets(fs, buffer, 400)))
00131 ok = false;
00132 if (ok)
00133 {
00134
00135 }
00136
00137
00138 if (ok && (!gzgets(fs, buffer, 400)))
00139 ok = false;
00140 if (ok)
00141 {
00142
00143 }
00144
00145
00146 gzclose(fs);
00147 if (ok)
00148 {
00149 FileInfo *info = new FileInfo;
00150
00151 int freq=0;
00152 FILE* hitdata = fopen( QFile::encodeName(CEF+"_freq"), "r+");
00153 if (hitdata && (freq=fgetc(hitdata))!=EOF)
00154 {
00155 freq+=fgetc(hitdata)<<8;
00156 if (freq>0)
00157 info->rating=age/freq;
00158 else
00159 info->rating=age;
00160 fclose(hitdata);
00161 }
00162 else
00163 info->rating = age;
00164 return info;
00165 }
00166
00167 unlink( CEF.data());
00168 return 0;
00169 }
00170
00171
00172
00173 void scanDirectory(FileInfoList &fileEntries, const QString &name, const QString &strDir)
00174 {
00175 QDir dir(strDir);
00176 if (!dir.exists()) return;
00177
00178 QFileInfoList newEntries = dir.entryInfoList();
00179
00180 if (newEntries.count()==0) return;
00181
00182 foreach ( const QFileInfo &qFileInfo, newEntries ) {
00183 if (qFileInfo.isFile())
00184 {
00185 FileInfo *fileInfo = readEntry( strDir + '/' + qFileInfo.fileName());
00186 if (fileInfo)
00187 {
00188 fileInfo->name = name + '/' + qFileInfo.fileName();
00189 fileInfo->size = (qFileInfo.size() + 1023) / 1024;
00190 fileEntries.append(fileInfo);
00191 }
00192 }
00193 }
00194 }
00195
00196 extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
00197 {
00198 KCmdLineArgs::init( argc, argv, appName, "kdelibs4",
00199 ki18n("KDE HTTP cache maintenance tool"), version,
00200 ki18n("KDE HTTP cache maintenance tool"), KCmdLineArgs::CmdLineArgNone);
00201
00202 KCmdLineOptions options;
00203 options.add("clear-all", ki18n("Empty the cache"));
00204
00205 KCmdLineArgs::addCmdLineOptions( options );
00206
00207 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00208
00209 bool deleteAll = args->isSet("clear-all");
00210
00211 KComponentData ins( appName );
00212
00213 if (!deleteAll)
00214 {
00215 if (!QDBusConnection::sessionBus().isConnected())
00216 {
00217 QDBusError error(QDBusConnection::sessionBus().lastError());
00218 fprintf(stderr, "%s: Could not connect to D-Bus! (%s: %s)\n", appName,
00219 qPrintable(error.name()), qPrintable(error.message()));
00220 return 1;
00221 }
00222
00223 if (!QDBusConnection::sessionBus().registerService(appFullName))
00224 {
00225 fprintf(stderr, "%s: Already running!\n", appName);
00226 return 0;
00227 }
00228 }
00229
00230 currentDate = time(0);
00231 m_maxCacheAge = KProtocolManager::maxCacheAge();
00232 m_maxCacheSize = KProtocolManager::maxCacheSize();
00233
00234 if (deleteAll)
00235 m_maxCacheSize = -1;
00236
00237 QString strCacheDir = KGlobal::dirs()->saveLocation("cache", "http");
00238
00239 QDir cacheDir( strCacheDir );
00240 if (!cacheDir.exists())
00241 {
00242 fprintf(stderr, "%s: '%s' does not exist.\n", appName, qPrintable(strCacheDir));
00243 return 0;
00244 }
00245
00246 const QStringList dirs = cacheDir.entryList( );
00247
00248 FileInfoList cachedEntries;
00249
00250 for(QStringList::ConstIterator it = dirs.begin();
00251 it != dirs.end();
00252 ++it)
00253 {
00254 if (it->at(0) != '.')
00255 {
00256 scanDirectory( cachedEntries, *it, strCacheDir + '/' + *it);
00257 }
00258 }
00259
00260 qSort(cachedEntries.begin(), cachedEntries.end());
00261
00262 int maxCachedSize = m_maxCacheSize / 2;
00263
00264 Q_FOREACH( FileInfo *fileInfo , cachedEntries )
00265 {
00266 if (fileInfo->size > maxCachedSize)
00267 {
00268 QByteArray filename = QFile::encodeName( strCacheDir + '/' + fileInfo->name);
00269 unlink(filename.data());
00270
00271 }
00272 }
00273
00274 int totalSize = 0;
00275
00276 Q_FOREACH( FileInfo *fileInfo , cachedEntries )
00277 {
00278 if ((totalSize + fileInfo->size) > m_maxCacheSize)
00279 {
00280 QByteArray filename = QFile::encodeName( strCacheDir + '/' + fileInfo->name);
00281 unlink(filename.data());
00282
00283 }
00284 else
00285 {
00286 totalSize += fileInfo->size;
00287
00288 }
00289 }
00290 kDebug (7113) << appName << ": Current size of cache = " << totalSize << " kB.";
00291 return 0;
00292 }
00293
00294