/*
 * Copyright (C) 2005, 2006, 2007 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. 
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR 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.
 */

#if ENABLE(NETSCAPE_PLUGIN_API)
#import "WebNetscapePluginStream.h"

#import "WebFrameInternal.h"
#import "WebKitErrorsPrivate.h"
#import "WebKitLogging.h"
#import "WebNSObjectExtras.h"
#import "WebNSURLExtras.h"
#import "WebNSURLRequestExtras.h"
#import "WebNetscapePluginPackage.h"
#import "WebNetscapePluginView.h"
#import "WebResourceLoadScheduler.h"
#import <Foundation/NSURLResponse.h>
#import <JavaScriptCore/JSLock.h>
#import <WebCore/CommonVM.h>
#import <WebCore/Document.h>
#import <WebCore/DocumentLoader.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
#import <WebCore/JSDOMWindowBase.h>
#import <WebCore/LoaderStrategy.h>
#import <WebCore/PlatformStrategies.h>
#import <WebCore/SecurityOrigin.h>
#import <WebCore/SecurityPolicy.h>
#import <WebCore/WebCoreURLResponse.h>
#import <pal/spi/cf/CFNetworkSPI.h>
#import <wtf/CompletionHandler.h>
#import <wtf/HashMap.h>
#import <wtf/NeverDestroyed.h>
#import <wtf/StdLibExtras.h>

using namespace WebCore;

#define WEB_REASON_NONE -1

class PluginStopDeferrer {
public:
    PluginStopDeferrer(WebNetscapePluginView* pluginView)
        : m_pluginView(pluginView)
    {
        ASSERT(m_pluginView);
        
        [m_pluginView.get() willCallPlugInFunction];
    }
    
    ~PluginStopDeferrer()
    {
        ASSERT(m_pluginView);
        [m_pluginView.get() didCallPlugInFunction];
    }
    
private:
    RetainPtr<WebNetscapePluginView> m_pluginView;
};

typedef HashMap<NPStream*, NPP> StreamMap;
static StreamMap& streams()
{
    static NeverDestroyed<StreamMap> staticStreams;
    return staticStreams;
}

NPP WebNetscapePluginStream::ownerForStream(NPStream *stream)
{
    return streams().get(stream);
}

NPReason WebNetscapePluginStream::reasonForError(NSError *error)
{
    if (!error)
        return NPRES_DONE;

    if ([[error domain] isEqualToString:NSURLErrorDomain] && [error code] == NSURLErrorCancelled)
        return NPRES_USER_BREAK;

    return NPRES_NETWORK_ERR;
}

NSError *WebNetscapePluginStream::pluginCancelledConnectionError() const
{
    return [[[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInCancelledConnection
                                           contentURL:m_responseURL ? m_responseURL.get() : (NSURL *)m_requestURL
                                        pluginPageURL:nil
                                           pluginName:[[m_pluginView.get() pluginPackage] pluginInfo].name
                                             MIMEType:(NSString *)String::fromUTF8(m_mimeType.data(), m_mimeType.length())] autorelease];
}

NSError *WebNetscapePluginStream::errorForReason(NPReason reason) const
{
    if (reason == NPRES_DONE)
        return nil;

    if (reason == NPRES_USER_BREAK)
        return [NSError _webKitErrorWithDomain:NSURLErrorDomain
                                          code:NSURLErrorCancelled 
                                           URL:m_responseURL ? m_responseURL.get() : (NSURL *)m_requestURL];

    return pluginCancelledConnectionError();
}

WebNetscapePluginStream::WebNetscapePluginStream(FrameLoader* frameLoader)
    : m_plugin(0)
    , m_transferMode(0)
    , m_offset(0)
    , m_fileDescriptor(-1)
    , m_sendNotification(false)
    , m_notifyData(0)
    , m_headers(0)
    , m_reason(NPRES_BASE)
    , m_isTerminated(false)
    , m_newStreamSuccessful(false)
    , m_frameLoader(frameLoader)
    , m_pluginFuncs(0)
    , m_deliverDataTimer(*this, &WebNetscapePluginStream::deliverData)
{
    memset(&m_stream, 0, sizeof(NPStream));
}

WebNetscapePluginStream::WebNetscapePluginStream(NSURLRequest *request, NPP plugin, bool sendNotification, void* notifyData)
    : m_requestURL([request URL])
    , m_plugin(0)
    , m_transferMode(0)
    , m_offset(0)
    , m_fileDescriptor(-1)
    , m_sendNotification(sendNotification)
    , m_notifyData(notifyData)
    , m_headers(0)
    , m_reason(NPRES_BASE)
    , m_isTerminated(false)
    , m_newStreamSuccessful(false)
    , m_frameLoader(0)
    , m_request(adoptNS([request mutableCopy]))
    , m_pluginFuncs(0)
    , m_deliverDataTimer(*this, &WebNetscapePluginStream::deliverData)
{
    memset(&m_stream, 0, sizeof(NPStream));

    WebNetscapePluginView *view = (WebNetscapePluginView *)plugin->ndata;
    
    // This check has already been done by the plug-in view.
    ASSERT(core([view webFrame])->document()->securityOrigin().canDisplay([request URL]));
    
    ASSERT([request URL]);
    ASSERT(plugin);
    
    setPlugin(plugin);
    
    streams().add(&m_stream, plugin);
    
    String referrer = SecurityPolicy::generateReferrerHeader(core([view webFrame])->document()->referrerPolicy(), [request URL], core([view webFrame])->loader().outgoingReferrer());
    if (referrer.isEmpty())
        [m_request.get() _web_setHTTPReferrer:nil];
    else
        [m_request.get() _web_setHTTPReferrer:referrer];
}

WebNetscapePluginStream::~WebNetscapePluginStream()
{
    ASSERT(!m_plugin);
    ASSERT(m_isTerminated);
    ASSERT(!m_stream.ndata);
    
    // The stream file should have been deleted, and the path freed, in -_destroyStream
    ASSERT(!m_path);
    ASSERT(m_fileDescriptor == -1);
    
    free((void *)m_stream.url);
    free(m_headers);
    
    streams().remove(&m_stream);
}

void WebNetscapePluginStream::setPlugin(NPP plugin)
{
    if (plugin) {
        m_plugin = plugin;
        m_pluginView = static_cast<WebNetscapePluginView *>(m_plugin->ndata);

        WebNetscapePluginPackage *pluginPackage = [m_pluginView.get() pluginPackage];
        
        m_pluginFuncs = [pluginPackage pluginFuncs];
    } else {
        WebNetscapePluginView *view = m_pluginView.get();
        m_plugin = 0;
        m_pluginFuncs = 0;
        
        [view disconnectStream:this];
        m_pluginView = 0;
    }        
}

void WebNetscapePluginStream::startStream(NSURL *url, long long expectedContentLength, NSDate *lastModifiedDate, const String& mimeType, NSData *headers)
{
    ASSERT(!m_isTerminated);
    
    m_responseURL = url;
    m_mimeType = mimeType.utf8();
    
    free((void *)m_stream.url);
    m_stream.url = strdup([m_responseURL.get() _web_URLCString]);

    m_stream.ndata = this;
    m_stream.end = expectedContentLength > 0 ? (uint32_t)expectedContentLength : 0;
    m_stream.lastmodified = (uint32_t)[lastModifiedDate timeIntervalSince1970];
    m_stream.notifyData = m_notifyData;

    if (headers) {
        unsigned len = [headers length];
        m_headers = (char*) malloc(len + 1);
        [headers getBytes:m_headers length:len];
        m_headers[len] = 0;
        m_stream.headers = m_headers;
    }
    
    m_transferMode = NP_NORMAL;
    m_offset = 0;
    m_reason = WEB_REASON_NONE;
    // FIXME: If WebNetscapePluginStream called our initializer we wouldn't have to do this here.
    m_fileDescriptor = -1;

    // FIXME: Need a way to check if stream is seekable

    NPError npErr;
    {
        PluginStopDeferrer deferrer(m_pluginView.get());
        npErr = m_pluginFuncs->newstream(m_plugin, m_mimeType.mutableData(), &m_stream, NO, &m_transferMode);
    }

    LOG(Plugins, "NPP_NewStream URL=%@ MIME=%s error=%d", m_responseURL.get(), m_mimeType.data(), npErr);

    if (npErr != NPERR_NO_ERROR) {
        LOG_ERROR("NPP_NewStream failed with error: %d responseURL: %@", npErr, m_responseURL.get());
        // Calling cancelLoadWithError: cancels the load, but doesn't call NPP_DestroyStream.
        cancelLoadWithError(pluginCancelledConnectionError());
        return;
    }

    m_newStreamSuccessful = true;

    switch (m_transferMode) {
        case NP_NORMAL:
            LOG(Plugins, "Stream type: NP_NORMAL");
            break;
        case NP_ASFILEONLY:
            LOG(Plugins, "Stream type: NP_ASFILEONLY");
            break;
        case NP_ASFILE:
            LOG(Plugins, "Stream type: NP_ASFILE");
            break;
        case NP_SEEK:
            LOG_ERROR("Stream type: NP_SEEK not yet supported");
            cancelLoadAndDestroyStreamWithError(pluginCancelledConnectionError());
            break;
        default:
            LOG_ERROR("unknown stream type");
    }
}

void WebNetscapePluginStream::start()
{
    ASSERT(m_request);
    ASSERT(!m_frameLoader);
    ASSERT(!m_loader);

    webResourceLoadScheduler().schedulePluginStreamLoad(*core([m_pluginView.get() webFrame]), *this, m_request.get(), [this, protectedThis = makeRef(*this)] (RefPtr<WebCore::NetscapePlugInStreamLoader>&& loader) {
        m_loader = WTFMove(loader);
    });
}

void WebNetscapePluginStream::stop()
{
    ASSERT(!m_frameLoader);
    
    if (!m_loader->isDone())
        cancelLoadAndDestroyStreamWithError(m_loader->cancelledError());
}

void WebNetscapePluginStream::willSendRequest(NetscapePlugInStreamLoader*, ResourceRequest&& request, const ResourceResponse&, CompletionHandler<void(WebCore::ResourceRequest&&)>&& callback)
{
    // FIXME: We should notify the plug-in with NPP_URLRedirectNotify here.
    callback(WTFMove(request));
}

void WebNetscapePluginStream::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& response)
{
    NSURLResponse *r = response.nsURLResponse();
    
    NSMutableData *theHeaders = nil;
    long long expectedContentLength = [r expectedContentLength];
    
    if ([r isKindOfClass:[NSHTTPURLResponse class]]) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)r;
        theHeaders = [NSMutableData dataWithCapacity:1024];
        
        // FIXME: it would be nice to be able to get the raw HTTP header block.
        // This includes the HTTP version, the real status text,
        // all headers in their original order and including duplicates,
        // and all original bytes verbatim, rather than sent through Unicode translation.
        // Unfortunately NSHTTPURLResponse doesn't provide access at that low a level.
        
        [theHeaders appendBytes:"HTTP " length:5];
        char statusStr[10];
        long statusCode = [httpResponse statusCode];
        snprintf(statusStr, sizeof(statusStr), "%ld", statusCode);
        [theHeaders appendBytes:statusStr length:strlen(statusStr)];
        [theHeaders appendBytes:" OK\n" length:4];
        
        // HACK: pass the headers through as UTF-8.
        // This is not the intended behavior; we're supposed to pass original bytes verbatim.
        // But we don't have the original bytes, we have NSStrings built by the URL loading system.
        // It hopefully shouldn't matter, since RFC2616/RFC822 require ASCII-only headers,
        // but surely someone out there is using non-ASCII characters, and hopefully UTF-8 is adequate here.
        // It seems better than NSASCIIStringEncoding, which will lose information if non-ASCII is used.
        
        NSDictionary *headerDict = [httpResponse allHeaderFields];
        NSArray *keys = [[headerDict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
        NSEnumerator *i = [keys objectEnumerator];
        NSString *k;
        while ((k = [i nextObject]) != nil) {
            NSString *v = [headerDict objectForKey:k];
            [theHeaders appendData:[k dataUsingEncoding:NSUTF8StringEncoding]];
            [theHeaders appendBytes:": " length:2];
            [theHeaders appendData:[v dataUsingEncoding:NSUTF8StringEncoding]];
            [theHeaders appendBytes:"\n" length:1];
        }
        
        // If the content is encoded (most likely compressed), then don't send its length to the plugin,
        // which is only interested in the decoded length, not yet known at the moment.
        // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic.
        NSString *contentEncoding = (NSString *)[[(NSHTTPURLResponse *)r allHeaderFields] objectForKey:@"Content-Encoding"];
        if (contentEncoding && ![contentEncoding isEqualToString:@"identity"])
            expectedContentLength = -1;
        
        // startStreamResponseURL:... will null-terminate.
    }
    
    startStream([r URL], expectedContentLength, [r _lastModifiedDate], response.mimeType(), theHeaders);
}

void WebNetscapePluginStream::startStreamWithResponse(NSURLResponse *response)
{
    didReceiveResponse(0, response);
}

bool WebNetscapePluginStream::wantsAllStreams() const
{
    if (!m_pluginFuncs->getvalue)
        return false;
    
    void *value = 0;
    NPError error;
    {
        PluginStopDeferrer deferrer(m_pluginView.get());
        JSC::JSLock::DropAllLocks dropAllLocks(commonVM());
        error = m_pluginFuncs->getvalue(m_plugin, NPPVpluginWantsAllNetworkStreams, &value);
    }
    if (error != NPERR_NO_ERROR)
        return false;
    
    return value;
}

void WebNetscapePluginStream::destroyStream()
{
    if (m_isTerminated)
        return;

    Ref<WebNetscapePluginStream> protect(*this);

    ASSERT(m_reason != WEB_REASON_NONE);
    ASSERT([m_deliveryData.get() length] == 0);
    
    m_deliverDataTimer.stop();

    if (m_stream.ndata) {
        if (m_reason == NPRES_DONE && (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)) {
            ASSERT(m_fileDescriptor == -1);
            ASSERT(m_path);

            PluginStopDeferrer deferrer(m_pluginView.get());
            m_pluginFuncs->asfile(m_plugin, &m_stream, [m_path.get() fileSystemRepresentation]);
            LOG(Plugins, "NPP_StreamAsFile responseURL=%@ path=%s", m_responseURL.get(), m_path.get());
        }

        if (m_path) {
            // Delete the file after calling NPP_StreamAsFile(), instead of in -dealloc/-finalize.  It should be OK
            // to delete the file here -- NPP_StreamAsFile() is always called immediately before NPP_DestroyStream()
            // (the stream destruction function), so there can be no expectation that a plugin will read the stream
            // file asynchronously after NPP_StreamAsFile() is called.
            unlink([m_path.get() fileSystemRepresentation]);
            m_path = 0;

            if (m_isTerminated)
                return;
        }

        if (m_fileDescriptor != -1) {
            // The file may still be open if we are destroying the stream before it completed loading.
            close(m_fileDescriptor);
            m_fileDescriptor = -1;
        }

        if (m_newStreamSuccessful) {
            PluginStopDeferrer deferrer(m_pluginView.get());
#if !LOG_DISABLED
            NPError npErr = 
#endif
            m_pluginFuncs->destroystream(m_plugin, &m_stream, m_reason);
            LOG(Plugins, "NPP_DestroyStream responseURL=%@ error=%d", m_responseURL.get(), npErr);
        }

        free(m_headers);
        m_headers = NULL;
        m_stream.headers = NULL;

        m_stream.ndata = 0;

        if (m_isTerminated)
            return;
    }

    if (m_sendNotification) {
        // NPP_URLNotify expects the request URL, not the response URL.
        PluginStopDeferrer deferrer(m_pluginView.get());
        m_pluginFuncs->urlnotify(m_plugin, m_requestURL.string().utf8().data(), m_reason, m_notifyData);
        LOG(Plugins, "NPP_URLNotify requestURL=%@ reason=%d", (NSURL *)m_requestURL, m_reason);
    }

    m_isTerminated = true;

    setPlugin(0);
}

void WebNetscapePluginStream::destroyStreamWithReason(NPReason reason)
{
    m_reason = reason;
    if (m_reason != NPRES_DONE) {
        // Stop any pending data from being streamed.
        [m_deliveryData.get() setLength:0];
    } else if ([m_deliveryData.get() length] > 0) {
        // There is more data to be streamed, don't destroy the stream now.
        return;
    }

    Ref<WebNetscapePluginStream> protect(*this);
    destroyStream();
    ASSERT(!m_stream.ndata);
}

void WebNetscapePluginStream::cancelLoadWithError(NSError *error)
{
    if (m_frameLoader) {
        ASSERT(!m_loader);
        
        DocumentLoader* documentLoader = m_frameLoader->activeDocumentLoader();
        ASSERT(documentLoader);
        
        if (documentLoader->isLoadingMainResource())
            documentLoader->cancelMainResourceLoad(error);
        return;
    }
    
    if (!m_loader->isDone())
        m_loader->cancel(error);
}

void WebNetscapePluginStream::destroyStreamWithError(NSError *error)
{
    destroyStreamWithReason(reasonForError(error));
}

void WebNetscapePluginStream::didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError& error)
{
    destroyStreamWithError(error);
}

void WebNetscapePluginStream::cancelLoadAndDestroyStreamWithError(NSError *error)
{
    Ref<WebNetscapePluginStream> protect(*this);
    cancelLoadWithError(error);
    destroyStreamWithError(error);
    setPlugin(0);
}    

void WebNetscapePluginStream::deliverData()
{
    if (!m_stream.ndata || [m_deliveryData.get() length] == 0)
        return;

    Ref<WebNetscapePluginStream> protect(*this);

    int32_t totalBytes = [m_deliveryData.get() length];
    int32_t totalBytesDelivered = 0;

    while (totalBytesDelivered < totalBytes) {
        PluginStopDeferrer deferrer(m_pluginView.get());
        int32_t deliveryBytes = m_pluginFuncs->writeready(m_plugin, &m_stream);
        LOG(Plugins, "NPP_WriteReady responseURL=%@ bytes=%d", m_responseURL.get(), deliveryBytes);

        if (m_isTerminated)
            return;

        if (deliveryBytes <= 0) {
            // Plug-in can't receive anymore data right now. Send it later.
            if (!m_deliverDataTimer.isActive())
                m_deliverDataTimer.startOneShot(0_s);
            break;
        } else {
            deliveryBytes = std::min(deliveryBytes, totalBytes - totalBytesDelivered);
            NSData *subdata = [m_deliveryData.get() subdataWithRange:NSMakeRange(totalBytesDelivered, deliveryBytes)];
            PluginStopDeferrer deferrer(m_pluginView.get());
            deliveryBytes = m_pluginFuncs->write(m_plugin, &m_stream, m_offset, [subdata length], const_cast<void*>([subdata bytes]));
            if (deliveryBytes < 0) {
                // Netscape documentation says that a negative result from NPP_Write means cancel the load.
                cancelLoadAndDestroyStreamWithError(pluginCancelledConnectionError());
                return;
            }
            deliveryBytes = std::min<int32_t>(deliveryBytes, [subdata length]);
            m_offset += deliveryBytes;
            totalBytesDelivered += deliveryBytes;
            LOG(Plugins, "NPP_Write responseURL=%@ bytes=%d total-delivered=%d/%d", m_responseURL.get(), deliveryBytes, m_offset, m_stream.end);
        }
    }

    if (totalBytesDelivered > 0) {
        if (totalBytesDelivered < totalBytes) {
            NSMutableData *newDeliveryData = [[NSMutableData alloc] initWithCapacity:totalBytes - totalBytesDelivered];
            [newDeliveryData appendBytes:static_cast<char*>(const_cast<void*>([m_deliveryData.get() bytes])) + totalBytesDelivered length:totalBytes - totalBytesDelivered];
            
            m_deliveryData = adoptNS(newDeliveryData);
        } else {
            [m_deliveryData.get() setLength:0];
            if (m_reason != WEB_REASON_NONE) 
                destroyStream();
        }
    }
}

void WebNetscapePluginStream::deliverDataToFile(NSData *data)
{
    if (m_fileDescriptor == -1 && !m_path) {
        NSString *temporaryFileMask = [NSTemporaryDirectory() stringByAppendingPathComponent:@"WebKitPlugInStreamXXXXXX"];
        char *temporaryFileName = strdup([temporaryFileMask fileSystemRepresentation]);
        m_fileDescriptor = mkstemp(temporaryFileName);
        if (m_fileDescriptor == -1) {
            LOG_ERROR("Can't create a temporary file.");
            // This is not a network error, but the only error codes are "network error" and "user break".
            destroyStreamWithReason(NPRES_NETWORK_ERR);
            free(temporaryFileName);
            return;
        }

        m_path = [NSString stringWithUTF8String:temporaryFileName];
        free(temporaryFileName);
    }

    int dataLength = [data length];
    if (!dataLength)
        return;

    int byteCount = write(m_fileDescriptor, [data bytes], dataLength);
    if (byteCount != dataLength) {
        // This happens only rarely, when we are out of disk space or have a disk I/O error.
        LOG_ERROR("error writing to temporary file, errno %d", errno);
        close(m_fileDescriptor);
        m_fileDescriptor = -1;

        // This is not a network error, but the only error codes are "network error" and "user break".
        destroyStreamWithReason(NPRES_NETWORK_ERR);
        m_path = 0;
    }
}

void WebNetscapePluginStream::didFinishLoading(NetscapePlugInStreamLoader*)
{
    if (!m_stream.ndata)
        return;
    
    if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY) {
        // Fake the delivery of an empty data to ensure that the file has been created
        deliverDataToFile([NSData data]);
        if (m_fileDescriptor != -1)
            close(m_fileDescriptor);
        m_fileDescriptor = -1;
    }
    
    destroyStreamWithReason(NPRES_DONE);
}

void WebNetscapePluginStream::didReceiveData(NetscapePlugInStreamLoader*, const char* bytes, int length)
{
    NSData *data = [[NSData alloc] initWithBytesNoCopy:(void*)bytes length:length freeWhenDone:NO];

    ASSERT([data length] > 0);
    
    if (m_transferMode != NP_ASFILEONLY) {
        if (!m_deliveryData)
            m_deliveryData = adoptNS([[NSMutableData alloc] initWithCapacity:[data length]]);
        [m_deliveryData.get() appendData:data];
        deliverData();
    }
    if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)
        deliverDataToFile(data);
    
    [data release];
}

#endif
