/*
- * DEBUG: section 25 MIME Parsing and Internal Icons
- * AUTHOR: Harvest Derived
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * 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, USA.
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
*
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
*/
+/* DEBUG: section 25 MIME Parsing and Internal Icons */
+
#include "squid.h"
-#include "disk.h"
#include "fde.h"
+#include "fs_io.h"
#include "globals.h"
#include "HttpHdrCc.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "internal.h"
-#include "Mem.h"
#include "MemBuf.h"
+#include "MemObject.h"
#include "mime.h"
#include "RequestFlags.h"
#include "SquidConfig.h"
#include "Store.h"
#include "StoreClient.h"
+#include <array>
+
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#define GET_HDR_SZ 1024
-
/* forward declarations */
static void mimeFreeMemory(void);
-static char const *mimeGetIcon(const char *fn);
+static const SBuf mimeGetIcon(const char *fn);
class MimeIcon : public StoreClient
{
+ MEMPROXY_CLASS(MimeIcon);
+
public:
- MimeIcon(const char *aName);
+ explicit MimeIcon(const char *aName);
~MimeIcon();
void setName(char const *);
- char const * getName() const;
+ SBuf getName() const;
void load();
- void created(StoreEntry *newEntry);
- MEMPROXY_CLASS(MimeIcon);
+
+ /* StoreClient API */
+ virtual void created(StoreEntry *);
private:
- MimeIcon();
- const char *icon_;
+ SBuf icon_;
char *url_;
};
-MEMPROXY_CLASS_INLINE(MimeIcon);
class MimeEntry
{
+ MEMPROXY_CLASS(MimeEntry);
+
public:
- MimeEntry(const char *aPattern, const regex_t &compiledPattern,
- const char *aContentType,
- const char *aContentEncoding, const char *aTransferMode,
- bool optionViewEnable, bool optionDownloadEnable,
- const char *anIconName);
+ explicit MimeEntry(const char *aPattern, const regex_t &compiledPattern,
+ const char *aContentType,
+ const char *aContentEncoding, const char *aTransferMode,
+ bool optionViewEnable, bool optionDownloadEnable,
+ const char *anIconName);
~MimeEntry();
- MEMPROXY_CLASS(MimeEntry);
const char *pattern;
regex_t compiled_pattern;
bool download_option;
MimeIcon theIcon;
MimeEntry *next;
-private:
- MimeEntry();
};
-MEMPROXY_CLASS_INLINE(MimeEntry);
static MimeEntry *MimeTable = NULL;
static MimeEntry **MimeTableTail = &MimeTable;
}
MimeIcon::MimeIcon(const char *aName) :
- icon_(xstrdup(aName))
+ url_(nullptr)
{
- url_ = xstrdup(internalLocalUri("/squid-internal-static/icons/", icon_));
+ setName(aName);
}
MimeIcon::~MimeIcon()
{
- safe_free (icon_);
- safe_free (url_);
+ xfree(url_);
}
void
MimeIcon::setName(char const *aString)
{
- safe_free (icon_);
- safe_free (url_);
- icon_ = xstrdup (aString);
- url_ = xstrdup (internalLocalUri("/squid-internal-static/icons/", icon_));
+ xfree(url_);
+ icon_ = aString;
+ url_ = xstrdup(internalLocalUri("/squid-internal-static/icons/", icon_));
}
-char const *
+SBuf
MimeIcon::getName() const
{
return icon_;
}
-char const *
+const SBuf
mimeGetIcon(const char *fn)
{
MimeEntry *m = mimeGetEntry(fn, 1);
- if (m == NULL)
- return NULL;
-
- if (!strcmp(m->theIcon.getName(), dash_str))
- return NULL;
+ if (!m || !m->theIcon.getName().cmp(dash_str))
+ return SBuf();
return m->theIcon.getName();
}
const char *
mimeGetIconURL(const char *fn)
{
- char const *icon = mimeGetIcon(fn);
+ SBuf icon(mimeGetIcon(fn));
- if (icon == NULL)
+ if (icon.isEmpty())
return null_string;
if (Config.icons.use_short_names) {
- static MemBuf mb;
- mb.reset();
- mb.Printf("/squid-internal-static/icons/%s", icon);
- return mb.content();
+ static SBuf mb;
+ mb.clear();
+ mb.append("/squid-internal-static/icons/");
+ mb.append(icon);
+ return mb.c_str();
} else {
return internalLocalUri("/squid-internal-static/icons/", icon);
}
return;
if ((fp = fopen(filename, "r")) == NULL) {
- debugs(25, DBG_IMPORTANT, "mimeInit: " << filename << ": " << xstrerror());
+ int xerrno = errno;
+ debugs(25, DBG_IMPORTANT, "mimeInit: " << filename << ": " << xstrerr(xerrno));
return;
}
}
m = new MimeEntry(pattern,re,type,encoding,mode,view_option,
- download_option,icon);
+ download_option,icon);
*MimeTableTail = m;
void
MimeIcon::load()
{
- const char *type = mimeGetContentType(icon_);
+ const char *type = mimeGetContentType(icon_.c_str());
if (type == NULL)
fatal("Unknown icon format while reading mime.conf\n");
}
void
-MimeIcon::created (StoreEntry *newEntry)
+MimeIcon::created(StoreEntry *newEntry)
{
/* if the icon is already in the store, do nothing */
if (!newEntry->isNull())
return;
+ // XXX: if a 204 is cached due to earlier load 'failure' we should try to reload.
- int fd;
- int n;
- RequestFlags flags;
- struct stat sb;
- LOCAL_ARRAY(char, path, MAXPATHLEN);
- char *buf;
+ // default is a 200 object with image data.
+ // set to the backup value of 204 on image loading errors
+ Http::StatusCode status = Http::scOkay;
- snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon_);
+ static char path[MAXPATHLEN];
+ *path = 0;
+ if (snprintf(path, sizeof(path)-1, "%s/" SQUIDSBUFPH, Config.icons.directory, SQUIDSBUFPRINT(icon_)) < 0) {
+ debugs(25, DBG_CRITICAL, "ERROR: icon file '" << Config.icons.directory << "/" << icon_ << "' path is longer than " << MAXPATHLEN << " bytes");
+ status = Http::scNoContent;
+ }
- fd = file_open(path, O_RDONLY | O_BINARY);
- if (fd < 0) {
- debugs(25, DBG_CRITICAL, "Problem opening icon file " << path << ": " << xstrerror());
- return;
+ int fd = -1;
+ errno = 0;
+ if (status == Http::scOkay && (fd = file_open(path, O_RDONLY | O_BINARY)) < 0) {
+ int xerrno = errno;
+ debugs(25, DBG_CRITICAL, "ERROR: opening icon file " << path << ": " << xstrerr(xerrno));
+ status = Http::scNoContent;
}
- if (fstat(fd, &sb) < 0) {
- debugs(25, DBG_CRITICAL, "Problem opening icon file. Fd: " << fd << ", fstat error " << xstrerror());
+
+ struct stat sb;
+ errno = 0;
+ if (status == Http::scOkay && fstat(fd, &sb) < 0) {
+ int xerrno = errno;
+ debugs(25, DBG_CRITICAL, "ERROR: opening icon file " << path << " FD " << fd << ", fstat error " << xstrerr(xerrno));
file_close(fd);
- return;
+ status = Http::scNoContent;
}
+ // fill newEntry with a canned 2xx response object
+ RequestFlags flags;
flags.cachable = true;
StoreEntry *e = storeCreateEntry(url_,url_,flags,Http::METHOD_GET);
assert(e != NULL);
HttpRequest *r = HttpRequest::CreateFromUrl(url_);
if (NULL == r)
- fatal("mimeLoadIcon: cannot parse internal URL");
+ fatalf("mimeLoadIcon: cannot parse internal URL: %s", url_);
- e->mem_obj->request = HTTPMSGLOCK(r);
+ e->mem_obj->request = r;
+ HTTPMSGLOCK(e->mem_obj->request);
HttpReply *reply = new HttpReply;
- reply->setHeaders(HTTP_OK, NULL, mimeGetContentType(icon_), sb.st_size, sb.st_mtime, -1);
+ if (status == Http::scNoContent)
+ reply->setHeaders(status, NULL, NULL, 0, -1, -1);
+ else
+ reply->setHeaders(status, NULL, mimeGetContentType(icon_.c_str()), sb.st_size, sb.st_mtime, -1);
reply->cache_control = new HttpHdrCc();
reply->cache_control->maxAge(86400);
reply->header.putCc(reply->cache_control);
e->replaceHttpReply(reply);
- /* read the file into the buffer and append it to store */
- buf = (char *)memAllocate(MEM_4K_BUF);
- while ((n = FD_READ_METHOD(fd, buf, 4096)) > 0)
- e->append(buf, n);
+ if (status == Http::scOkay) {
+ /* read the file into the buffer and append it to store */
+ int n;
+ std::array<char, 4096> buf;
+ while ((n = FD_READ_METHOD(fd, buf.data(), buf.size())) > 0)
+ e->append(buf.data(), n);
+
+ file_close(fd);
+ }
- file_close(fd);
e->flush();
e->complete();
e->timestampsSet();
- e->unlock();
- memFree(buf, MEM_4K_BUF);
+ e->unlock("MimeIcon::created");
debugs(25, 3, "Loaded icon " << url_);
}
MimeEntry::~MimeEntry()
{
- safe_free(pattern);
- safe_free(content_type);
- safe_free(content_encoding);
+ xfree(pattern);
+ xfree(content_type);
+ xfree(content_encoding);
regfree(&compiled_pattern);
}
MimeEntry::MimeEntry(const char *aPattern, const regex_t &compiledPattern,
- const char *aContentType, const char *aContentEncoding,
- const char *aTransferMode, bool optionViewEnable,
- bool optionDownloadEnable, const char *anIconName) :
- pattern(xstrdup(aPattern)),
- compiled_pattern(compiledPattern),
- content_type(xstrdup(aContentType)),
- content_encoding(xstrdup(aContentEncoding)),
- view_option(optionViewEnable),
- download_option(optionViewEnable),
- theIcon(anIconName), next(NULL)
+ const char *aContentType, const char *aContentEncoding,
+ const char *aTransferMode, bool optionViewEnable,
+ bool optionDownloadEnable, const char *anIconName) :
+ pattern(xstrdup(aPattern)),
+ compiled_pattern(compiledPattern),
+ content_type(xstrdup(aContentType)),
+ content_encoding(xstrdup(aContentEncoding)),
+ view_option(optionViewEnable),
+ download_option(optionDownloadEnable),
+ theIcon(anIconName), next(NULL)
{
if (!strcasecmp(aTransferMode, "ascii"))
transfer_mode = 'A';
else
transfer_mode = 'I';
}
+