/*
  Copyright (C) 2000-2003 SKYRIX Software AG

  This file is part of OGo

  OGo is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version.

  OGo 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 Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with OGo; see the file COPYING.  If not, write to the
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
*/
// $Id$

#include "WOInput.h"
#include "common.h"
#import <NGMime/NGMime.h>
#import <NGHttp/NGHttp.h>

@interface WOFileUpload : WOInput
{
  // WODynamicElement: extraAttributes
  // WODynamicElement: otherTagString
  // inherited: name
  // inherited: value
  // inherited: disabled
@protected
  WOAssociation *filePath; // dispostion 'filename'
  WOAssociation *data;     // uploaded data
}

@end /* WOFileUpload */

@interface WORequest(UsedPrivates)
- (id)httpRequest;
@end

@implementation WOFileUpload

static NGMimeType *multipartFormData = nil;

+ (void)initialize {
  static BOOL isInitialized = NO;
  if (!isInitialized) {
    isInitialized = YES;

    multipartFormData = [NGMimeType mimeType:@"multipart/form-data"];
    multipartFormData = RETAIN(multipartFormData);
  }
}

- (id)initWithName:(NSString *)_name
  associations:(NSDictionary *)_config
  template:(WOElement *)_root {

  if ((self = [super initWithName:_name associations:_config template:_root])) {
    self->filePath = OWGetProperty(_config, @"filePath");
    self->data     = OWGetProperty(_config, @"data");
  }
  return self;
}

#if !LIB_FOUNDATION_BOEHM_GC
- (void)dealloc {
  RELEASE(self->filePath); self->filePath = nil;
  RELEASE(self->data);     self->data     = nil;
  [super dealloc];
}
#endif

// ******************** responder ********************

- (void)takeValuesFromRequest:(WORequest *)_request
  inContext:(WOContext *)_ctx
{
  if (![self->disabled boolValueInComponent:[_ctx component]]) {
    NSString *currentId;
    id       formValue  = nil;

    currentId = OWFormElementName(self, _ctx);

    formValue = [_request formValueForKey:currentId];
    if (formValue) {
      NGMimeType *contentType = [[_request httpRequest] contentType];
      
      if (![contentType hasSameType:multipartFormData]) {
        NSLog(@"WARNING: tried to apply file-upload value of %@ from "
              @"a non multipart-form request (value=%@) !",
              [_ctx elementID], formValue);
        return;
      }
  
      //NSLog(@"%@: value=%@ ..", [self elementID], formValue);

      if ([self->data isValueSettable])
        [self->data setValue:formValue inComponent:[_ctx component]];

      if ([self->filePath isValueSettable]) {
        NGMimeMultipartBody *body = [[_request httpRequest] body];

        if ([body isKindOfClass:[NGMimeMultipartBody class]]) {
          NSArray  *parts   = [body parts];
          unsigned i, count = [parts count];

          // search for part of current form element
          
          for (i = 0; i < count; i++) {
            id disposition;
            id<NGMimePart> bodyPart;
            
            bodyPart = [parts objectAtIndex:i];
            disposition =
              [[bodyPart valuesOfHeaderFieldWithName:@"content-disposition"]
                         nextObject];
            
            if (disposition) {
              static Class DispClass = Nil;
              NSString *formName;
              
              if (DispClass == Nil)
                DispClass = [NGMimeContentDispositionHeaderField class];
              
              if (![disposition isKindOfClass:DispClass]) {
                disposition =
                  [[DispClass alloc] initWithString:[disposition stringValue]];
                AUTORELEASE(disposition);
              }
              
              formName =
		[(NGMimeContentDispositionHeaderField *)disposition name];
              
              if ([formName isEqualToString:currentId]) {
                [self->filePath
		     setValue:[disposition filename]
                     inComponent:[_ctx component]];
                break;
              }
            }
          }
        }
      }
    }
  }
}

- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
  if (![[_ctx request] isFromClientComponent]) {
    NSString *v = [self->value stringValueInComponent:[_ctx component]];
      
    WOResponse_AddCString(_response, "<input type=\"file\" name=\"");
    [_response appendContentHTMLAttributeValue:OWFormElementName(self, _ctx)];
    WOResponse_AddChar(_response, '"');
    if (v) {
      WOResponse_AddCString(_response, " value=\"");
      [_response appendContentHTMLAttributeValue:v];
      WOResponse_AddChar(_response, '"');
    }
    [self appendExtraAttributesToResponse:_response inContext:_ctx];
  
    if (self->otherTagString) {
      WOResponse_AddString(_response,
                           [self->otherTagString stringValueInComponent:
                                [_ctx component]]);
    }
    WOResponse_AddCString(_response, " />");
  }
}

/* description */

- (NSString *)associationDescription {
  NSMutableString *str = [[NSMutableString alloc] init];
  [str appendString:[super associationDescription]];

  if (self->filePath) [str appendFormat:@" path=%@", self->filePath];
  if (self->data)     [str appendFormat:@" data=%@", self->data];

  return AUTORELEASE(str);
}

@end /* WOFileUpload */
