18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(FTPDIR)
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FTPDirectoryDocument.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
29f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include "HTMLDocumentParser.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLTableElement.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "LocalizedStrings.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Logging.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FTPDirectoryParser.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SegmentedString.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Settings.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SharedBuffer.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Text.h"
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h>
40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include <wtf/text/StringConcatenate.h>
415e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#include <wtf/CurrentTime.h>
425e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#include <wtf/StdLibExtras.h>
432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h>
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
51f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickclass FTPDirectoryDocumentParser : public HTMLDocumentParser {
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
53e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    static PassRefPtr<FTPDirectoryDocumentParser> create(HTMLDocument* document)
54e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    {
55e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return adoptRef(new FTPDirectoryDocumentParser(document));
56e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
58ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    virtual void append(const SegmentedString&);
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual void finish();
60f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    virtual bool isWaitingForScripts() const { return false; }
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    inline void checkBuffer(int len = 10)
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if ((m_dest - m_buffer) > m_size - len) {
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Enlarge buffer
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int newSize = max(m_size * 2, m_size + len);
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int oldOffset = m_dest - m_buffer;
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_buffer = static_cast<UChar*>(fastRealloc(m_buffer, newSize * sizeof(UChar)));
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_dest = m_buffer + oldOffset;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_size = newSize;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
76e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    FTPDirectoryDocumentParser(HTMLDocument*);
77e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
78545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    // The parser will attempt to load the document template specified via the preference
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Failing that, it will fall back and create the basic document which will have a minimal
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // table for presenting the FTP directory in a useful manner
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool loadDocumentTemplate();
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void createBasicDocument();
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void parseAndAppendOneLine(const String&);
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void appendEntry(const String& name, const String& size, const String& date, bool isDirectory);
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PassRefPtr<Element> createTDForFilename(const String&);
87f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<HTMLTableElement> m_tableElement;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool m_skipLF;
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool m_parsedTemplate;
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int m_size;
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* m_buffer;
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* m_dest;
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String m_carryOver;
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ListState m_listState;
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFTPDirectoryDocumentParser::FTPDirectoryDocumentParser(HTMLDocument* document)
102f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    : HTMLDocumentParser(document, false)
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_skipLF(false)
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_parsedTemplate(false)
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_size(254)
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_buffer(static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size)))
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_dest(m_buffer)
108ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
109f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
111545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid FTPDirectoryDocumentParser::appendEntry(const String& filename, const String& size, const String& date, bool isDirectory)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec;
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Element> rowElement = m_tableElement->insertRow(-1, ec);
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rowElement->setAttribute("class", "ftpDirectoryEntryRow", ec);
117f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
11806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    RefPtr<Element> element = document()->createElement(tdTag, false);
11906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    element->appendChild(Text::create(document(), String(&noBreakSpace, 1)), ec);
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isDirectory)
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeDirectory", ec);
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeFile", ec);
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rowElement->appendChild(element, ec);
125f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    element = createTDForFilename(filename);
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    element->setAttribute("class", "ftpDirectoryFileName", ec);
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rowElement->appendChild(element, ec);
129f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
13006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    element = document()->createElement(tdTag, false);
13106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    element->appendChild(Text::create(document(), date), ec);
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    element->setAttribute("class", "ftpDirectoryFileDate", ec);
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rowElement->appendChild(element, ec);
134f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
13506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    element = document()->createElement(tdTag, false);
13606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    element->appendChild(Text::create(document(), size), ec);
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    element->setAttribute("class", "ftpDirectoryFileSize", ec);
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    rowElement->appendChild(element, ec);
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
141545e470e52f0ac6a3a072bf559c796b42c6066b6Ben MurdochPassRefPtr<Element> FTPDirectoryDocumentParser::createTDForFilename(const String& filename)
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec;
144f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
14506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    String fullURL = document()->baseURL().string();
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fullURL[fullURL.length() - 1] == '/')
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fullURL.append(filename);
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fullURL.append("/" + filename);
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    RefPtr<Element> anchorElement = document()->createElement(aTag, false);
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    anchorElement->setAttribute("href", fullURL, ec);
15306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    anchorElement->appendChild(Text::create(document(), filename), ec);
154f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
15506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    RefPtr<Element> tdElement = document()->createElement(tdTag, false);
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    tdElement->appendChild(anchorElement, ec);
157f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return tdElement.release();
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic String processFilesizeString(const String& size, bool isDirectory)
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isDirectory)
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return "--";
165f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool valid;
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int64_t bytes = size.toUInt64(&valid);
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!valid)
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return unknownFileSizeText();
170f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (bytes < 1000000)
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return String::format("%.2f KB", static_cast<float>(bytes)/1000);
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (bytes < 1000000000)
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return String::format("%.2f MB", static_cast<float>(bytes)/1000000);
176f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return String::format("%.2f GB", static_cast<float>(bytes)/1000000000);
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool wasLastDayOfMonth(int year, int month, int day)
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static int lastDays[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (month < 0 || month > 11)
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
185f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (month == 2) {
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (year % 4 == 0 && (year % 100 || year % 400 == 0)) {
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (day == 29)
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return true;
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
192f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (day == 28)
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
197f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return lastDays[month] == day;
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic String processFileDateString(const FTPTime& fileTime)
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Need to localize this string?
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String timeOfDay;
206f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!(fileTime.tm_hour == 0 && fileTime.tm_min == 0 && fileTime.tm_sec == 0)) {
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int hour = fileTime.tm_hour;
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(hour >= 0 && hour < 24);
210f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (hour < 12) {
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (hour == 0)
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                hour = 12;
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            timeOfDay = String::format(", %i:%02i AM", hour, fileTime.tm_min);
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            hour = hour - 12;
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (hour == 0)
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                hour = 12;
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            timeOfDay = String::format(", %i:%02i PM", hour, fileTime.tm_min);
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
222f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If it was today or yesterday, lets just do that - but we have to compare to the current time
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    struct tm now;
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    time_t now_t = time(NULL);
2265e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    getLocalTime(&now_t, &now);
227f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // localtime does "year = current year - 1900", compensate for that for readability and comparison purposes
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    now.tm_year += 1900;
230f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fileTime.tm_year == now.tm_year) {
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (fileTime.tm_mon == now.tm_mon) {
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (fileTime.tm_mday == now.tm_mday)
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return "Today" + timeOfDay;
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (fileTime.tm_mday == now.tm_mday - 1)
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return "Yesterday" + timeOfDay;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (now.tm_mday == 1 && (now.tm_mon == fileTime.tm_mon + 1 || (now.tm_mon == 0 && fileTime.tm_mon == 11)) &&
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            wasLastDayOfMonth(fileTime.tm_year, fileTime.tm_mon, fileTime.tm_mday))
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return "Yesterday" + timeOfDay;
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
243f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fileTime.tm_year == now.tm_year - 1 && fileTime.tm_mon == 12 && fileTime.tm_mday == 31 && now.tm_mon == 1 && now.tm_mday == 1)
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return "Yesterday" + timeOfDay;
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
248f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int month = fileTime.tm_mon;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (month < 0 || month > 11)
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        month = 12;
252f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String dateString;
254f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (fileTime.tm_year > -1)
256a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        dateString = makeString(months[month], ' ', String::number(fileTime.tm_mday), ", ", String::number(fileTime.tm_year));
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
258a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        dateString = makeString(months[month], ' ', String::number(fileTime.tm_mday), ", ", String::number(now.tm_year));
259f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return dateString + timeOfDay;
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
263545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid FTPDirectoryDocumentParser::parseAndAppendOneLine(const String& inputLine)
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ListResult result;
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    CString latin1Input = inputLine.latin1();
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    FTPEntryType typeResult = parseOneFTPLine(latin1Input.data(), m_listState, result);
269f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FTPMiscEntry is a comment or usage statistic which we don't care about, and junk is invalid data - bail in these 2 cases
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (typeResult == FTPMiscEntry || typeResult == FTPJunkEntry)
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
273f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String filename(result.filename, result.filenameLength);
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result.type == FTPDirectoryEntry) {
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        filename.append("/");
277f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We have no interest in linking to "current directory"
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (filename == "./")
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(FTP, "Appending entry - %s, %s", filename.ascii().data(), result.fileSize.ascii().data());
284f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    appendEntry(filename, processFilesizeString(result.fileSize, result.type == FTPDirectoryEntry), processFileDateString(result.modifiedTime), result.type == FTPDirectoryEntry);
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic inline PassRefPtr<SharedBuffer> createTemplateDocumentData(Settings* settings)
289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    RefPtr<SharedBuffer> buffer = 0;
291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (settings)
292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        buffer = SharedBuffer::createWithContentsOfFile(settings->ftpDirectoryTemplatePath());
293635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (buffer)
294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        LOG(FTP, "Loaded FTPDirectoryTemplate of length %i\n", buffer->size());
295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return buffer.release();
296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
298545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochbool FTPDirectoryDocumentParser::loadDocumentTemplate()
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
30006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    DEFINE_STATIC_LOCAL(RefPtr<SharedBuffer>, templateDocumentData, (createTemplateDocumentData(document()->settings())));
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Instead of storing the data, we'd rather actually parse the template data into the template Document once,
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // store that document, then "copy" it whenever we get an FTP directory listing.  There are complexities with this
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // approach that make it worth putting this off.
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!templateDocumentData) {
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ERROR("Could not load templateData");
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
309ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
310f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    HTMLDocumentParser::insert(String(templateDocumentData->data(), templateDocumentData->size()));
311f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
31206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    RefPtr<Element> tableElement = document()->getElementById("ftpDirectoryTable");
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!tableElement)
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ERROR("Unable to find element by id \"ftpDirectoryTable\" in the template document.");
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (!tableElement->hasTagName(tableTag))
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ERROR("Element of id \"ftpDirectoryTable\" is not a table element");
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_tableElement = static_cast<HTMLTableElement*>(tableElement.get());
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Bail if we found the table element
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_tableElement)
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Otherwise create one manually
32506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    tableElement = document()->createElement(tableTag, false);
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_tableElement = static_cast<HTMLTableElement*>(tableElement.get());
3278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ExceptionCode ec;
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_tableElement->setAttribute("id", "ftpDirectoryTable", ec);
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If we didn't find the table element, lets try to append our own to the body
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If that fails for some reason, cram it on the end of the document as a last
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ditch effort
33306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (Element* body = document()->body())
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        body->appendChild(m_tableElement, ec);
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
33606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        document()->appendChild(m_tableElement, ec);
337f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
341545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid FTPDirectoryDocumentParser::createBasicDocument()
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG(FTP, "Creating a basic FTP document structure as no template was loaded");
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Make this "basic document" more acceptable
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
34706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    RefPtr<Element> bodyElement = document()->createElement(bodyTag, false);
348f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ExceptionCode ec;
35006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    document()->appendChild(bodyElement, ec);
351f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
35206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    RefPtr<Element> tableElement = document()->createElement(tableTag, false);
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_tableElement = static_cast<HTMLTableElement*>(tableElement.get());
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_tableElement->setAttribute("id", "ftpDirectoryTable", ec);
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bodyElement->appendChild(m_tableElement, ec);
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
359ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockvoid FTPDirectoryDocumentParser::append(const SegmentedString& source)
360ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Make sure we have the table element to append to by loading the template set in the pref, or
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // creating a very basic document with the appropriate table
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_tableElement) {
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!loadDocumentTemplate())
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            createBasicDocument();
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_tableElement);
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
368f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool foundNewLine = false;
370f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_dest = m_buffer;
372ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    SegmentedString str = source;
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!str.isEmpty()) {
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        UChar c = *str;
375f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (c == '\r') {
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *m_dest++ = '\n';
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            foundNewLine = true;
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // possibly skip an LF in the case of an CRLF sequence
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_skipLF = true;
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (c == '\n') {
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!m_skipLF)
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                *m_dest++ = c;
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_skipLF = false;
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *m_dest++ = c;
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_skipLF = false;
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
390f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        str.advance();
392f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Maybe enlarge the buffer
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        checkBuffer();
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
396f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!foundNewLine) {
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_dest = m_buffer;
3998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* start = m_buffer;
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    UChar* cursor = start;
404f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (cursor < m_dest) {
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (*cursor == '\n') {
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_carryOver.append(String(start, cursor - start));
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOG(FTP, "%s", m_carryOver.ascii().data());
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            parseAndAppendOneLine(m_carryOver);
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_carryOver = String();
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            start = ++cursor;
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            cursor++;
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
416f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Copy the partial line we have left to the carryover buffer
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (cursor - start > 1)
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_carryOver.append(String(start, cursor - start - 1));
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
422545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid FTPDirectoryDocumentParser::finish()
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Possible the last line in the listing had no newline, so try to parse it now
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_carryOver.isEmpty()) {
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        parseAndAppendOneLine(m_carryOver);
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_carryOver = String();
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
429f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_tableElement = 0;
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fastFree(m_buffer);
432f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
433f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    HTMLDocumentParser::finish();
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
43606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFTPDirectoryDocument::FTPDirectoryDocument(Frame* frame, const KURL& url)
43706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    : HTMLDocument(frame, url)
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LogFTP.state = WTFLogChannelOn;
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
444e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockPassRefPtr<DocumentParser> FTPDirectoryDocument::createParser()
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
446e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return FTPDirectoryDocumentParser::create(this);
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(FTPDIR)
452