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
00028 #include <time.h>
00029 #include <stdlib.h>
00030
00031 #include <qdir.h>
00032 #include <qstring.h>
00033 #include <qptrlist.h>
00034
00035 #include <kinstance.h>
00036 #include <klocale.h>
00037 #include <kcmdlineargs.h>
00038 #include <kglobal.h>
00039 #include <kstandarddirs.h>
00040 #include <dcopclient.h>
00041 #include <kprotocolmanager.h>
00042
00043 #include <unistd.h>
00044
00045 #include <kdebug.h>
00046
00047 time_t currentDate;
00048 int m_maxCacheAge;
00049 int m_maxCacheSize;
00050
00051 static const char appName[] = "kio_http_cache_cleaner";
00052
00053 static const char description[] = I18N_NOOP("KDE HTTP cache maintenance tool");
00054
00055 static const char version[] = "1.0.0";
00056
00057 static const KCmdLineOptions options[] =
00058 {
00059 {"clear-all", I18N_NOOP("Empty the cache"), 0},
00060 KCmdLineLastOption
00061 };
00062
00063 struct FileInfo {
00064 QString name;
00065 int size;
00066 int age;
00067 };
00068
00069 template class QPtrList<FileInfo>;
00070
00071 class FileInfoList : public QPtrList<FileInfo>
00072 {
00073 public:
00074 FileInfoList() : QPtrList<FileInfo>() { }
00075 int compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2)
00076 { return ((FileInfo *)item1)->age - ((FileInfo *)item2)->age; }
00077 };
00078
00079
00080
00081 #define CACHE_REVISION "7\n"
00082
00083 FileInfo *readEntry( const QString &filename)
00084 {
00085 QCString CEF = QFile::encodeName(filename);
00086 FILE *fs = fopen( CEF.data(), "r");
00087 if (!fs)
00088 return 0;
00089
00090 char buffer[401];
00091 bool ok = true;
00092
00093
00094 if (ok && (!fgets(buffer, 400, fs)))
00095 ok = false;
00096 if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
00097 ok = false;
00098
00099
00100 if (ok && (!fgets(buffer, 400, fs)))
00101 ok = false;
00102
00103 time_t creationDate;
00104 int age =0;
00105
00106
00107 if (ok && (!fgets(buffer, 400, fs)))
00108 ok = false;
00109 if (ok)
00110 {
00111 creationDate = (time_t) strtoul(buffer, 0, 10);
00112 age = (int) difftime(currentDate, creationDate);
00113 if ( m_maxCacheAge && ( age > m_maxCacheAge))
00114 {
00115 ok = false;
00116 }
00117 }
00118
00119
00120 if (ok && (!fgets(buffer, 400, fs)))
00121 ok = false;
00122 if (ok)
00123 {
00124
00125 #if 0
00126 time_t expireDate;
00127 expireDate = (time_t) strtoul(buffer, 0, 10);
00128 if (expireDate && (expireDate < currentDate))
00129 ok = false;
00130 #endif
00131 }
00132
00133
00134 if (ok && (!fgets(buffer, 400, fs)))
00135 ok = false;
00136 if (ok)
00137 {
00138
00139 }
00140
00141
00142 if (ok && (!fgets(buffer, 400, fs)))
00143 ok = false;
00144 if (ok)
00145 {
00146
00147 }
00148
00149
00150 fclose(fs);
00151 if (ok)
00152 {
00153 FileInfo *info = new FileInfo;
00154 info->age = age;
00155 return info;
00156 }
00157
00158 unlink( CEF.data());
00159 return 0;
00160 }
00161
00162
00163
00164 void scanDirectory(FileInfoList &fileEntries, const QString &name, const QString &strDir)
00165 {
00166 QDir dir(strDir);
00167 if (!dir.exists()) return;
00168
00169 QFileInfoList *newEntries = (QFileInfoList *) dir.entryInfoList();
00170
00171 if (!newEntries) return;
00172
00173 for(QFileInfo *qFileInfo = newEntries->first();
00174 qFileInfo;
00175 qFileInfo = newEntries->next())
00176 {
00177 if (qFileInfo->isFile())
00178 {
00179 FileInfo *fileInfo = readEntry( strDir + "/" + qFileInfo->fileName());
00180 if (fileInfo)
00181 {
00182 fileInfo->name = name + "/" + qFileInfo->fileName();
00183 fileInfo->size = (qFileInfo->size() + 1023) / 1024;
00184 fileEntries.append(fileInfo);
00185 }
00186 }
00187 }
00188 }
00189
00190 extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
00191 {
00192 KLocale::setMainCatalogue("kdelibs");
00193 KCmdLineArgs::init( argc, argv, appName,
00194 I18N_NOOP("KDE HTTP cache maintenance tool"),
00195 description, version, true);
00196
00197 KCmdLineArgs::addCmdLineOptions( options );
00198
00199 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00200
00201 bool deleteAll = args->isSet("clear-all");
00202
00203 KInstance ins( appName );
00204
00205 if (!deleteAll)
00206 {
00207 DCOPClient *dcop = new DCOPClient();
00208 QCString name = dcop->registerAs(appName, false);
00209 if (!name.isEmpty() && (name != appName))
00210 {
00211 fprintf(stderr, "%s: Already running! (%s)\n", appName, name.data());
00212 return 0;
00213 }
00214 }
00215
00216 currentDate = time(0);
00217 m_maxCacheAge = KProtocolManager::maxCacheAge();
00218 m_maxCacheSize = KProtocolManager::maxCacheSize();
00219
00220 if (deleteAll)
00221 m_maxCacheSize = -1;
00222
00223 QString strCacheDir = KGlobal::dirs()->saveLocation("cache", "http");
00224
00225 QDir cacheDir( strCacheDir );
00226 if (!cacheDir.exists())
00227 {
00228 fprintf(stderr, "%s: '%s' does not exist.\n", appName, strCacheDir.ascii());
00229 return 0;
00230 }
00231
00232 QStringList dirs = cacheDir.entryList( );
00233
00234 FileInfoList cachedEntries;
00235
00236 for(QStringList::Iterator it = dirs.begin();
00237 it != dirs.end();
00238 it++)
00239 {
00240 if ((*it)[0] != '.')
00241 {
00242 scanDirectory( cachedEntries, *it, strCacheDir + "/" + *it);
00243 }
00244 }
00245
00246 cachedEntries.sort();
00247
00248 int maxCachedSize = m_maxCacheSize / 2;
00249
00250 for(FileInfo *fileInfo = cachedEntries.first();
00251 fileInfo;
00252 fileInfo = cachedEntries.next())
00253 {
00254 if (fileInfo->size > maxCachedSize)
00255 {
00256 QCString filename = QFile::encodeName( strCacheDir + "/" + fileInfo->name);
00257 unlink(filename.data());
00258
00259 }
00260 }
00261
00262 int totalSize = 0;
00263
00264 for(FileInfo *fileInfo = cachedEntries.first();
00265 fileInfo;
00266 fileInfo = cachedEntries.next())
00267 {
00268 if ((totalSize + fileInfo->size) > m_maxCacheSize)
00269 {
00270 QCString filename = QFile::encodeName( strCacheDir + "/" + fileInfo->name);
00271 unlink(filename.data());
00272
00273 }
00274 else
00275 {
00276 totalSize += fileInfo->size;
00277
00278 }
00279 }
00280 kdDebug () << appName << ": Current size of cache = " << totalSize << " kB." << endl;
00281 return 0;
00282 }
00283
00284