summaryrefslogtreecommitdiffstats
path: root/WebCore/loader/FTPDirectoryDocument.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/loader/FTPDirectoryDocument.cpp')
-rw-r--r--WebCore/loader/FTPDirectoryDocument.cpp493
1 files changed, 0 insertions, 493 deletions
diff --git a/WebCore/loader/FTPDirectoryDocument.cpp b/WebCore/loader/FTPDirectoryDocument.cpp
deleted file mode 100644
index 0a7e91e..0000000
--- a/WebCore/loader/FTPDirectoryDocument.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#if ENABLE(FTPDIR)
-#include "FTPDirectoryDocument.h"
-
-#include "CharacterNames.h"
-#include "CString.h"
-#include "HTMLNames.h"
-#include "HTMLTableElement.h"
-#include "HTMLTokenizer.h"
-#include "LocalizedStrings.h"
-#include "Logging.h"
-#include "FTPDirectoryParser.h"
-#include "SegmentedString.h"
-#include "Settings.h"
-#include "SharedBuffer.h"
-#include "Text.h"
-
-#if PLATFORM(QT)
-#include <QDateTime>
-// On Windows, use the threadsafe *_r functions provided by pthread.
-#elif PLATFORM(WIN_OS) && (USE(PTHREADS) || HAVE(PTHREAD_H))
-#include <pthread.h>
-#endif
-
-using namespace std;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-class FTPDirectoryTokenizer : public HTMLTokenizer {
-public:
- FTPDirectoryTokenizer(HTMLDocument*);
-
- virtual bool write(const SegmentedString&, bool appendData);
- virtual void finish();
-
- virtual bool isWaitingForScripts() const { return false; }
-
- inline void checkBuffer(int len = 10)
- {
- if ((m_dest - m_buffer) > m_size - len) {
- // Enlarge buffer
- int newSize = max(m_size * 2, m_size + len);
- int oldOffset = m_dest - m_buffer;
- m_buffer = static_cast<UChar*>(fastRealloc(m_buffer, newSize * sizeof(UChar)));
- m_dest = m_buffer + oldOffset;
- m_size = newSize;
- }
- }
-
-private:
- // The tokenizer will attempt to load the document template specified via the preference
- // Failing that, it will fall back and create the basic document which will have a minimal
- // table for presenting the FTP directory in a useful manner
- bool loadDocumentTemplate();
- void createBasicDocument();
-
- void parseAndAppendOneLine(const String&);
- void appendEntry(const String& name, const String& size, const String& date, bool isDirectory);
- PassRefPtr<Element> createTDForFilename(const String&);
-
- Document* m_doc;
- RefPtr<HTMLTableElement> m_tableElement;
-
- bool m_skipLF;
- bool m_parsedTemplate;
-
- int m_size;
- UChar* m_buffer;
- UChar* m_dest;
- String m_carryOver;
-
- ListState m_listState;
-};
-
-FTPDirectoryTokenizer::FTPDirectoryTokenizer(HTMLDocument* doc)
- : HTMLTokenizer(doc, false)
- , m_doc(doc)
- , m_skipLF(false)
- , m_parsedTemplate(false)
- , m_size(254)
- , m_buffer(static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size)))
- , m_dest(m_buffer)
-{
-}
-
-void FTPDirectoryTokenizer::appendEntry(const String& filename, const String& size, const String& date, bool isDirectory)
-{
- ExceptionCode ec;
-
- RefPtr<Element> rowElement = m_tableElement->insertRow(-1, ec);
- rowElement->setAttribute("class", "ftpDirectoryEntryRow", ec);
-
- RefPtr<Element> element = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec);
- element->appendChild(new Text(m_doc, String(&noBreakSpace, 1)), ec);
- if (isDirectory)
- element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeDirectory", ec);
- else
- element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeFile", ec);
- rowElement->appendChild(element, ec);
-
- element = createTDForFilename(filename);
- element->setAttribute("class", "ftpDirectoryFileName", ec);
- rowElement->appendChild(element, ec);
-
- element = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec);
- element->appendChild(new Text(m_doc, date), ec);
- element->setAttribute("class", "ftpDirectoryFileDate", ec);
- rowElement->appendChild(element, ec);
-
- element = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec);
- element->appendChild(new Text(m_doc, size), ec);
- element->setAttribute("class", "ftpDirectoryFileSize", ec);
- rowElement->appendChild(element, ec);
-}
-
-PassRefPtr<Element> FTPDirectoryTokenizer::createTDForFilename(const String& filename)
-{
- ExceptionCode ec;
-
- String fullURL = m_doc->baseURL().string();
- if (fullURL[fullURL.length() - 1] == '/')
- fullURL.append(filename);
- else
- fullURL.append("/" + filename);
-
- RefPtr<Element> anchorElement = m_doc->createElementNS(xhtmlNamespaceURI, "a", ec);
- anchorElement->setAttribute("href", fullURL, ec);
- anchorElement->appendChild(new Text(m_doc, filename), ec);
-
- RefPtr<Element> tdElement = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec);
- tdElement->appendChild(anchorElement, ec);
-
- return tdElement.release();
-}
-
-static String processFilesizeString(const String& size, bool isDirectory)
-{
- if (isDirectory)
- return "--";
-
- bool valid;
- int64_t bytes = size.toUInt64(&valid);
- if (!valid)
- return unknownFileSizeText();
-
- if (bytes < 1000000)
- return String::format("%.2f KB", static_cast<float>(bytes)/1000);
-
- if (bytes < 1000000000)
- return String::format("%.2f MB", static_cast<float>(bytes)/1000000);
-
- return String::format("%.2f GB", static_cast<float>(bytes)/1000000000);
-}
-
-static bool wasLastDayOfMonth(int year, int month, int day)
-{
- static int lastDays[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- if (month < 0 || month > 11)
- return false;
-
- if (month == 2) {
- if (year % 4 == 0 && (year % 100 || year % 400 == 0)) {
- if (day == 29)
- return true;
- return false;
- }
-
- if (day == 28)
- return true;
- return false;
- }
-
- return lastDays[month] == day;
-}
-
-#if PLATFORM(QT)
-
-/*!
- Replacement for localtime_r() which is not available on MinGW.
-
- We use this on all of Qt's platforms for portability.
- */
-struct tm gmtimeQt(const QDateTime &input)
-{
- tm result;
-
- const QDate date(input.date());
- result.tm_year = date.year() - 1900;
- result.tm_mon = date.month();
- result.tm_mday = date.day();
- result.tm_wday = date.dayOfWeek();
- result.tm_yday = date.dayOfYear();
-
- const QTime time(input.time());
- result.tm_sec = time.second();
- result.tm_min = time.minute();
- result.tm_hour = time.hour();
-
- return result;
-}
-
-static struct tm *localTimeQt(const time_t *const timep, struct tm *result)
-{
- const QDateTime dt(QDateTime::fromTime_t(*timep));
- *result = WebCore::gmtimeQt(dt.toLocalTime());
- return result;
-}
-
-#define localtime_r(x, y) localTimeQt(x, y)
-#elif PLATFORM(WIN_OS) && !defined(localtime_r)
-#define localtime_r(x, y) localtime_s((y), (x))
-#endif
-
-static String processFileDateString(const FTPTime& fileTime)
-{
- // FIXME: Need to localize this string?
-
- String timeOfDay;
-
- if (!(fileTime.tm_hour == 0 && fileTime.tm_min == 0 && fileTime.tm_sec == 0)) {
- int hour = fileTime.tm_hour;
- ASSERT(hour >= 0 && hour < 24);
-
- if (hour < 12) {
- if (hour == 0)
- hour = 12;
- timeOfDay = String::format(", %i:%02i AM", hour, fileTime.tm_min);
- } else {
- hour = hour - 12;
- if (hour == 0)
- hour = 12;
- timeOfDay = String::format(", %i:%02i PM", hour, fileTime.tm_min);
- }
- }
-
- // If it was today or yesterday, lets just do that - but we have to compare to the current time
- struct tm now;
- time_t now_t = time(NULL);
- localtime_r(&now_t, &now);
-
- // localtime does "year = current year - 1900", compensate for that for readability and comparison purposes
- now.tm_year += 1900;
-
- if (fileTime.tm_year == now.tm_year) {
- if (fileTime.tm_mon == now.tm_mon) {
- if (fileTime.tm_mday == now.tm_mday)
- return "Today" + timeOfDay;
- if (fileTime.tm_mday == now.tm_mday - 1)
- return "Yesterday" + timeOfDay;
- }
-
- if (now.tm_mday == 1 && (now.tm_mon == fileTime.tm_mon + 1 || now.tm_mon == 0 && fileTime.tm_mon == 11) &&
- wasLastDayOfMonth(fileTime.tm_year, fileTime.tm_mon, fileTime.tm_mday))
- return "Yesterday" + timeOfDay;
- }
-
- if (fileTime.tm_year == now.tm_year - 1 && fileTime.tm_mon == 12 && fileTime.tm_mday == 31 && now.tm_mon == 1 && now.tm_mday == 1)
- return "Yesterday" + timeOfDay;
-
- static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
-
- int month = fileTime.tm_mon;
- if (month < 0 || month > 11)
- month = 12;
-
- String dateString;
-
- if (fileTime.tm_year > -1)
- dateString = String::format("%s %i, %i", months[month], fileTime.tm_mday, fileTime.tm_year);
- else
- dateString = String::format("%s %i, %i", months[month], fileTime.tm_mday, now.tm_year);
-
- return dateString + timeOfDay;
-}
-
-void FTPDirectoryTokenizer::parseAndAppendOneLine(const String& inputLine)
-{
- ListResult result;
-
- FTPEntryType typeResult = parseOneFTPLine(inputLine.latin1().data(), m_listState, result);
-
- // FTPMiscEntry is a comment or usage statistic which we don't care about, and junk is invalid data - bail in these 2 cases
- if (typeResult == FTPMiscEntry || typeResult == FTPJunkEntry)
- return;
-
- String filename(result.filename, result.filenameLength);
- if (result.type == FTPDirectoryEntry) {
- filename.append("/");
-
- // We have no interest in linking to "current directory"
- if (filename == "./")
- return;
- }
-
- LOG(FTP, "Appending entry - %s, %s", filename.ascii().data(), result.fileSize.ascii().data());
-
- appendEntry(filename, processFilesizeString(result.fileSize, result.type == FTPDirectoryEntry), processFileDateString(result.modifiedTime), result.type == FTPDirectoryEntry);
-}
-
-bool FTPDirectoryTokenizer::loadDocumentTemplate()
-{
- static RefPtr<SharedBuffer> templateDocumentData;
- // FIXME: Instead of storing the data, we'd rather actually parse the template data into the template Document once,
- // store that document, then "copy" it whenever we get an FTP directory listing. There are complexities with this
- // approach that make it worth putting this off.
-
- if (!templateDocumentData) {
- Settings* settings = m_doc->settings();
- if (settings)
- templateDocumentData = SharedBuffer::createWithContentsOfFile(settings->ftpDirectoryTemplatePath());
- if (templateDocumentData)
- LOG(FTP, "Loaded FTPDirectoryTemplate of length %i\n", templateDocumentData->size());
- }
-
- if (!templateDocumentData) {
- LOG_ERROR("Could not load templateData");
- return false;
- }
-
- // Tokenize the template as an HTML document synchronously
- setForceSynchronous(true);
- HTMLTokenizer::write(String(templateDocumentData->data(), templateDocumentData->size()), true);
- setForceSynchronous(false);
-
- RefPtr<Element> tableElement = m_doc->getElementById("ftpDirectoryTable");
- if (!tableElement)
- LOG_ERROR("Unable to find element by id \"ftpDirectoryTable\" in the template document.");
- else if (!tableElement->hasTagName(tableTag))
- LOG_ERROR("Element of id \"ftpDirectoryTable\" is not a table element");
- else
- m_tableElement = static_cast<HTMLTableElement*>(tableElement.get());
-
- // Bail if we found the table element
- if (m_tableElement)
- return true;
-
- // Otherwise create one manually
- ExceptionCode ec;
- tableElement = m_doc->createElementNS(xhtmlNamespaceURI, "table", ec);
- m_tableElement = static_cast<HTMLTableElement*>(tableElement.get());
- m_tableElement->setAttribute("id", "ftpDirectoryTable", ec);
-
- // If we didn't find the table element, lets try to append our own to the body
- // If that fails for some reason, cram it on the end of the document as a last
- // ditch effort
- if (Element* body = m_doc->body())
- body->appendChild(m_tableElement, ec);
- else
- m_doc->appendChild(m_tableElement, ec);
-
- return true;
-}
-
-void FTPDirectoryTokenizer::createBasicDocument()
-{
- LOG(FTP, "Creating a basic FTP document structure as no template was loaded");
-
- // FIXME: Make this "basic document" more acceptable
-
- ExceptionCode ec;
-
- RefPtr<Element> bodyElement = m_doc->createElementNS(xhtmlNamespaceURI, "body", ec);
-
- m_doc->appendChild(bodyElement, ec);
-
- RefPtr<Element> tableElement = m_doc->createElementNS(xhtmlNamespaceURI, "table", ec);
- m_tableElement = static_cast<HTMLTableElement*>(tableElement.get());
- m_tableElement->setAttribute("id", "ftpDirectoryTable", ec);
-
- bodyElement->appendChild(m_tableElement, ec);
-}
-
-bool FTPDirectoryTokenizer::write(const SegmentedString& s, bool appendData)
-{
- // Make sure we have the table element to append to by loading the template set in the pref, or
- // creating a very basic document with the appropriate table
- if (!m_tableElement) {
- if (!loadDocumentTemplate())
- createBasicDocument();
- ASSERT(m_tableElement);
- }
-
- bool foundNewLine = false;
-
- m_dest = m_buffer;
- SegmentedString str = s;
- while (!str.isEmpty()) {
- UChar c = *str;
-
- if (c == '\r') {
- *m_dest++ = '\n';
- foundNewLine = true;
- // possibly skip an LF in the case of an CRLF sequence
- m_skipLF = true;
- } else if (c == '\n') {
- if (!m_skipLF)
- *m_dest++ = c;
- else
- m_skipLF = false;
- } else {
- *m_dest++ = c;
- m_skipLF = false;
- }
-
- str.advance();
-
- // Maybe enlarge the buffer
- checkBuffer();
- }
-
- if (!foundNewLine) {
- m_dest = m_buffer;
- return false;
- }
-
- UChar* start = m_buffer;
- UChar* cursor = start;
-
- while (cursor < m_dest) {
- if (*cursor == '\n') {
- m_carryOver.append(String(start, cursor - start));
- LOG(FTP, "%s", m_carryOver.ascii().data());
- parseAndAppendOneLine(m_carryOver);
- m_carryOver = String();
-
- start = ++cursor;
- } else
- cursor++;
- }
-
- // Copy the partial line we have left to the carryover buffer
- if (cursor - start > 1)
- m_carryOver.append(String(start, cursor - start - 1));
-
- return false;
-}
-
-void FTPDirectoryTokenizer::finish()
-{
- // Possible the last line in the listing had no newline, so try to parse it now
- if (!m_carryOver.isEmpty()) {
- parseAndAppendOneLine(m_carryOver);
- m_carryOver = String();
- }
-
- m_tableElement = 0;
- fastFree(m_buffer);
-
- HTMLTokenizer::finish();
-}
-
-FTPDirectoryDocument::FTPDirectoryDocument(Frame* frame)
- : HTMLDocument(frame)
-{
-#ifndef NDEBUG
- LogFTP.state = WTFLogChannelOn;
-#endif
-}
-
-Tokenizer* FTPDirectoryDocument::createTokenizer()
-{
- return new FTPDirectoryTokenizer(this);
-}
-
-}
-
-#endif // ENABLE(FTPDIR)