mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-02-23 03:31:16 +00:00
* GSWeb.framework/GSWWOCompatibility.h/.m: added * GSWeb.framework/GNUmakefile: added GSWWOCompatibility.h/.m * GSWeb.framework/GSWApplication.h/m: added WOApplicationMain, handle WO/GSWeb names * GSWeb.framework/GSWContext.m: handle WO/GSWeb names, added traces * GSWeb.framework/GSWConstants.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWDynamicURLString.m: handle WO/GSWeb names * GSWeb.framework/GSWProjectBundle.m/.h: handle WO/GSWeb names, suppress warnings * GSWeb.framework/GSWSession.m: handle WO/GSWeb names * GSWeb.framework/GSWRequest.m: handle WO/GSWeb names * GSWeb.framework/GSWTemplateParser.m: handle WO/GSWeb names, added tag counts to help errors hunt * GSWeb.framework/GSWBundle.m: handle WO/GSWeb names, added traces * GSWeb.framework/GSWResourceManager.m: handle WO/GSWeb names * GSWeb.framework/GSWURLValuedElementData.m: handle WO/GSWeb names * GSWeb.framework/GSWComponentRequestHandler.m: handle WO/GSWeb names * GSWeb.framework/GSWDirectAction.m: handle WO/GSWeb names * GSWeb.framework/GSWForm.m/.h: handle WO/GSWeb names * GSWeb.framework/GSWHyperlink.m/.h: handle WO/GSWeb names * GSWeb.framework/GSWResourceRequestHandler.m: handle WO/GSWeb names * GSWeb.framework/GSWDirectActionRequestHandler.m: handle WO/GSWeb names * GSWeb.framework/GSWActiveImage.m/.h: handle WO/GSWeb names * GSWeb.framework/GSWBindingNameAssociation.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWBrowser.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWComponent.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWHTMLURLValuedElement.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWImageButton.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWInput.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWPopUpButton.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWString.h/.m: handle WO/GSWeb names * GSWeb.framework/GSWAssociation.m: handle WO/GSWeb names * GSWeb.framework/GSWCheckBox.m: handle WO/GSWeb names * GSWeb.framework/GSWCheckBoxList.m: handle WO/GSWeb names * GSWeb.framework/GSWComponentDefinition.m: handle WO/GSWeb names * GSWeb.framework/GSWRadioButton.m: handle WO/GSWeb names * GSWeb.framework/GSWRadioButtonList.m: handle WO/GSWeb names * GSWeb.framework/GSWText.m: handle WO/GSWeb names * GSWeb.framework/GSWTextField.m: handle WO/GSWeb names * GSWeb.framework/GSWDeployedBundle.m: warnings * GSWeb.framework/GSWeb.h: added include GSWeb/GSWSessionTimeOut.h, GSWWOCompatibility.h * GSWeb.framework/GSWAdaptor.m: traces * GSWeb.framework/GSWDefaultAdaptor.m: handle WO/GSWeb names, added traces * GSWeb.framework/GSWDefaultAdaptorThread.m/.h: handle WO/GSWeb names * GSWeb.framework/NSNonBlockingFileHandle.m: added traces * GSWeb.framework/GSWTemplateParserANTLR.m: handle WO/GSWeb names * GSWeb.framework/GSWTemplateParserXML.m: handle WO/GSWeb names added tag count to help errors hunt remove "Tag gsweb invalid" message handle unicode strings in node content traces remove html and body tags if they are not present in the template * GSWeb.framework/GSWTemplateParseXML.h: added ivar _isHTMLTag, _isBodyTag * GSWeb.framework/GSWSessionTimeOutManager.m: dealloc sessionOrderedTimeOuts instead of deallocating 2 times sessionTimeOuts * GSWExtensions.framework/French.lproj/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html: tag mismatch, Encode french characters * GSWExtensions.framework/GSWSessionRestorationErrorPage.gswc/GSWSessionRestorationErrorPage.html: tag mismatch * GSWHTMLBareString.m: handle unicode strings in description * GSWExtensions.framework/French.lproj/GSWExceptionPage.gswc/GSWExceptionPage.html: Encode french characters, Tag Mismatch * GSWExtensions.framework/French.lproj/GSWPageRestorationErrorPage.gswc/GSWPageRestorationErrorPage.html: Encode french characters * GSWExtensions.framework/French.lproj/GSWSessionCreationErrorPage.gswc/GSWSessionCreationErrorPage.html: Encode french characters * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.html: Tag Mismatch * GSWExtensions.framework/GSWExceptionPage.gswc/GSWExceptionPage.gswd: added convertHTMLEntities for strings * GSWeb.framework/GSWRepetition.m: added traces, fix "count" property bug, standardize ivars * GSWeb.framework/NSObject+IVarAccess+PerformSel.m: added traces, handle underscored ivars search git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@9332 72102866-910b-0410-8b05-ffd578937521
620 lines
20 KiB
Objective-C
620 lines
20 KiB
Objective-C
/* GSWDefaultAdaptorThread.m - GSWeb: Class GSWDefaultAdaptorThread
|
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
Written by: Manuel Guesdon <mguesdon@sbuilders.com>
|
|
Date: Feb 1999
|
|
|
|
This file is part of the GNUstep Web Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
static char rcsId[] = "$Id$";
|
|
|
|
#include <GSWeb/GSWeb.h>
|
|
#include <unistd.h>
|
|
#include "NSNonBlockingFileHandle.h"
|
|
//====================================================================
|
|
@implementation GSWDefaultAdaptorThread
|
|
|
|
//--------------------------------------------------------------------
|
|
-(id)init
|
|
{
|
|
if ((self=[super init]))
|
|
{
|
|
ASSIGN(creationDate,[NSDate date]);
|
|
requestNamingConv=GSWebNamingConv;//GSWNAMES_INDEX or WONAMES_INDEX
|
|
};
|
|
return self;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(id)initWithApp:(GSWApplication*)application_
|
|
withAdaptor:(GSWAdaptor*)adaptor_
|
|
withStream:(NSFileHandle*)stream_
|
|
{
|
|
if ((self=[self init]))
|
|
{
|
|
application=application_;
|
|
adaptor=adaptor_;
|
|
ASSIGN(stream,stream_);
|
|
keepAlive=NO;
|
|
isMultiThread=[adaptor isMultiThreadEnabled];
|
|
NSDebugMLLog(@"info",@"isMultiThread=%d",(int)isMultiThread);
|
|
};
|
|
return self;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)dealloc
|
|
{
|
|
GSWLogC("dealloc GSWDefaultAdaptorThread");
|
|
DESTROY(stream);
|
|
GSWLogC("release dates");
|
|
DESTROY(creationDate);
|
|
DESTROY(runDate);
|
|
DESTROY(dispatchRequestDate);
|
|
DESTROY(sendResponseDate);
|
|
GSWLogC("release pool");
|
|
// DESTROY(pool);
|
|
[super dealloc];
|
|
GSWLogC("dealloc GSWDefaultAdaptorThread end");
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(GSWAdaptor*)adaptor
|
|
{
|
|
return adaptor;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(NSAutoreleasePool*)pool
|
|
{
|
|
return pool;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)setPool:(NSAutoreleasePool*)pool_
|
|
destroyLast:(BOOL)destroy_
|
|
{
|
|
if (destroy_)
|
|
{
|
|
DESTROY(pool);
|
|
};
|
|
pool=pool_;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)run:(id)void_
|
|
{
|
|
BOOL _requestOk=NO;
|
|
NSMutableDictionary* _threadDictionary=nil;
|
|
NSString* _requestLine=nil;
|
|
NSDictionary* _headers=nil;
|
|
NSData* _data=nil;
|
|
ASSIGN(runDate,[NSDate date]);
|
|
DESTROY(dispatchRequestDate);
|
|
DESTROY(sendResponseDate);
|
|
[GSWApplication statusLogWithFormat:@"Thread run START"];
|
|
pool=[NSAutoreleasePool new];
|
|
[GSWApplication logWithFormat:@"pool allocated!"];
|
|
if (isMultiThread)
|
|
{
|
|
_threadDictionary=GSCurrentThreadDictionary();
|
|
[_threadDictionary setObject:self
|
|
forKey:GSWThreadKey_DefaultAdaptorThread];
|
|
[[NSNotificationCenter defaultCenter] addObserver:[self class]
|
|
selector:@selector(threadExited:)
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
object:[NSThread currentThread]];
|
|
/*
|
|
[NotificationDispatcher addObserver:[self class]
|
|
selector:@selector(threadExited:)
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
object:[NSThread currentThread]];
|
|
*/
|
|
};
|
|
NSDebugMLLog(@"low",@"application:%@",application);
|
|
|
|
NS_DURING
|
|
{
|
|
_requestOk=[self readRequestReturnedRequestLine:&_requestLine
|
|
returnedHeaders:&_headers
|
|
returnedData:&_data];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGException(@"GSWDefaultAdaptorThread: readRequestFromStream Exception:%@ (%@)",localException,[localException reason]);
|
|
}
|
|
NS_ENDHANDLER;
|
|
if (!_requestOk)
|
|
{
|
|
//TODO
|
|
}
|
|
else
|
|
{
|
|
GSWRequest* request=nil;
|
|
GSWResponse* response=nil;
|
|
NSDebugMLLog(@"info",@"GSWDefaultAdaptorThread: runWithStream requestLine=%@ _headers=%@ _data=%@",
|
|
_requestLine,
|
|
_headers,
|
|
_data);
|
|
NS_DURING
|
|
{
|
|
request=[self createRequestFromRequestLine:_requestLine
|
|
headers:_headers
|
|
data:_data];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGException(@"GSWDefaultAdaptorThread: createRequestFromData Exception:%@ (%@)",localException,[localException reason]);
|
|
}
|
|
NS_ENDHANDLER;
|
|
if (request)
|
|
{
|
|
//call application resourceRequestHandlerKey (retourne wr)
|
|
//call requets requestHandlerKey (retorune nil)
|
|
NSDebugMLLog(@"info",@"GSWDefaultAdaptorThread: run handleRequest:%@",request);
|
|
ASSIGN(dispatchRequestDate,[NSDate date]);
|
|
NS_DURING
|
|
{
|
|
response=[application dispatchRequest:request];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
BOOL _isApplicationRequestHandlingLocked=[application isRequestHandlingLocked];
|
|
LOGException(@"GSWDefaultAdaptorThread: dispatchRequest Exception:%@ (%@)%s",
|
|
localException,
|
|
[localException reason],
|
|
_isApplicationRequestHandlingLocked ? " Request Handling Locked !" : "");
|
|
}
|
|
NS_ENDHANDLER;
|
|
if (!response)
|
|
{
|
|
response=[GSWResponse responseWithMessage:@"Application returned no response"
|
|
inContext:nil
|
|
forRequest:request];
|
|
[response _finalizeInContext:nil]; //DO Call _finalizeInContext: !
|
|
};
|
|
if (response)
|
|
{
|
|
RETAIN(response);
|
|
ASSIGN(sendResponseDate,[NSDate date]);
|
|
NS_DURING
|
|
{
|
|
[self sendResponse:response];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
LOGException(@"GSWDefaultAdaptorThread: sendResponse Exception:%@ (%@)",localException,[localException reason]);
|
|
}
|
|
NS_ENDHANDLER;
|
|
NSDebugMLLog(@"low",@"application:%@",application);
|
|
AUTORELEASE(response);
|
|
};
|
|
};
|
|
};
|
|
NSDebugMLog0(@"GSWDefaultAdaptorThread: run end");
|
|
NSDebugMLLog(@"low",@"application:%@",application);
|
|
LOGObjectFnStop();
|
|
[GSWApplication statusLogWithFormat:@"threadWillExit START"];
|
|
[application threadWillExit];
|
|
[GSWApplication statusLogWithFormat:@"threadWillExit STOP"];
|
|
if (isMultiThread)
|
|
{
|
|
NSAssert([NSThread isMultiThreaded],@"No MultiThread !");
|
|
[NSThread exit]; //???
|
|
}
|
|
else
|
|
[self threadExited];
|
|
[GSWApplication statusLogWithFormat:@"run STOP"];
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)threadExited
|
|
{
|
|
// LOGObjectFnStart();
|
|
NSDebugMLLog(@"low",@"[_defaultAdaptorThread retainCount=%d",
|
|
(int)[self retainCount]);
|
|
[adaptor adaptorThreadExited:self];
|
|
[self setPool:nil
|
|
destroyLast:YES];
|
|
// LOGObjectFnStop();
|
|
GSWLogC("threadExited");
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(id)threadExited:(NSNotification*)notif_
|
|
{
|
|
NSThread* _thread=nil;
|
|
NSMutableDictionary* _threadDict=nil;
|
|
GSWDefaultAdaptorThread* _adaptorThread=nil;
|
|
GSWLogC("Start threadExited:");
|
|
NSAssert([NSThread isMultiThreaded],@"No MultiThread !");
|
|
NSDebugMLLog(@"low",@"notif_=%@",notif_);
|
|
_thread=[notif_ object];
|
|
NSDebugMLLog(@"low",@"_thread=%@",_thread);
|
|
_threadDict = [_thread threadDictionary];
|
|
NSDebugMLLog(@"low",@"_threadDict=%@",_threadDict);
|
|
_adaptorThread=[_threadDict objectForKey:GSWThreadKey_DefaultAdaptorThread];
|
|
NSDebugMLLog(@"low",@"_adaptorThread=%@",_adaptorThread);
|
|
[_threadDict removeObjectForKey:GSWThreadKey_DefaultAdaptorThread];
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
object:_thread];
|
|
/* [NotificationDispatcher removeObserver:self
|
|
name:NSThreadExiting//NSThreadWillExitNotification
|
|
object:_thread];
|
|
*/
|
|
[_adaptorThread threadExited];
|
|
GSWLogC("Stop threadExited:");
|
|
GSWLogC("threadExited really exit");
|
|
return nil; //??
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
+(NSMutableArray*)completeLinesWithData:(NSMutableData*)data_
|
|
returnedConsumedCount:(int*)consumedCount_
|
|
returnedHeadersEndFlag:(BOOL*)headersEndFlag_
|
|
{
|
|
NSMutableArray* _lines=nil;
|
|
int _length=0;
|
|
LOGClassFnStart();
|
|
_length=[data_ length];
|
|
if (_length>0)
|
|
{
|
|
NSRange _range=NSMakeRange(0,0);
|
|
int i=0;
|
|
char* _dataBytes=(char*)[data_ mutableBytes];
|
|
BOOL _endHeaders=NO;
|
|
while(!_endHeaders && i<_length)
|
|
{
|
|
if (_dataBytes[i]=='\n')
|
|
{
|
|
if (_range.length>0)
|
|
{
|
|
NSString* tmpString=[[[NSString alloc]initWithData:[data_ subdataWithRange:_range]
|
|
encoding:NSASCIIStringEncoding]autorelease];
|
|
if (!_lines)
|
|
_lines=[NSMutableArray array];
|
|
[_lines addObject:tmpString];
|
|
}
|
|
else // End Header
|
|
{
|
|
_endHeaders=YES;
|
|
};
|
|
_range.location=i+1;
|
|
_range.length=0;
|
|
}
|
|
else
|
|
_range.length++;
|
|
i++;
|
|
};
|
|
_range.length=_length-_range.location;
|
|
if (_range.length>0)
|
|
memcpy(_dataBytes,_dataBytes+_range.location,_range.length);
|
|
[data_ setLength:_range.length];
|
|
if (consumedCount_)
|
|
*consumedCount_=_length-_range.length;
|
|
if (headersEndFlag_)
|
|
*headersEndFlag_=_endHeaders;
|
|
};
|
|
LOGClassFnStop();
|
|
return _lines;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(BOOL)readRequestReturnedRequestLine:(NSString**)requestLine_
|
|
returnedHeaders:(NSDictionary**)headers_
|
|
returnedData:(NSData**)data_
|
|
{
|
|
BOOL ok=NO;
|
|
LOGObjectFnStart();
|
|
if (!stream)
|
|
{
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"no stream");
|
|
}
|
|
else
|
|
{
|
|
#define REQUEST_METHOD__UNKNOWN 0
|
|
#define REQUEST_METHOD__GET 1
|
|
#define REQUEST_METHOD__POST 2
|
|
NSMutableData* _pendingData=nil;
|
|
NSDate* maxDate=[NSDate dateWithTimeIntervalSinceNow:360]; //360s
|
|
NSData* dataBlock=nil;
|
|
int sleepTime=250; //250ms
|
|
int readenBytesNb=0;
|
|
int headersBytesNb=0;
|
|
int dataBytesNb=0;
|
|
int dataBlockLength=0;
|
|
int contentLength=-1;
|
|
int _requestMethod=REQUEST_METHOD__UNKNOWN;
|
|
BOOL _isRequestLineSetted=NO;
|
|
BOOL _isDataStep=NO;
|
|
BOOL _isAllDataReaden=NO;
|
|
BOOL _isElapsed=NO;
|
|
NSMutableDictionary* _headers=nil;
|
|
NSString* _userAgent=nil;
|
|
NSString* _remoteAddr=nil;
|
|
NSDebugMLog0(@"dataBlock try reading");
|
|
do
|
|
{
|
|
dataBlock=[stream availableDataNonBlocking];
|
|
dataBlockLength=[dataBlock length];
|
|
NSDebugMLog(@"dataBlockLength=%i",dataBlockLength);
|
|
if (dataBlockLength>0)
|
|
{
|
|
readenBytesNb+=dataBlockLength;
|
|
if (!_pendingData)
|
|
_pendingData=(NSMutableData*)[NSMutableData data];
|
|
[_pendingData appendData:dataBlock];
|
|
if (_isDataStep)
|
|
dataBytesNb=[_pendingData length];
|
|
else
|
|
{
|
|
int _newBytesCount=0;
|
|
NSMutableArray* _newLines=[GSWDefaultAdaptorThread completeLinesWithData:_pendingData
|
|
returnedConsumedCount:&_newBytesCount
|
|
returnedHeadersEndFlag:&_isDataStep];
|
|
NSDebugMLLog(@"low",@"newLines=%@ isDataStep=%s newBytesCount=%d",
|
|
_newLines,
|
|
_isDataStep ? "YES" : "NO",
|
|
_newBytesCount);
|
|
headersBytesNb+=_newBytesCount;
|
|
if (_newLines)
|
|
{
|
|
int i=0;
|
|
for(i=0;i<[_newLines count];i++)
|
|
{
|
|
NSString* _line=[_newLines objectAtIndex:i];
|
|
NSDebugMLLog(@"low",@"Line:%@",_line);
|
|
NSAssert([_line length]>0,@"No line length");
|
|
if (!_isRequestLineSetted)
|
|
{
|
|
*requestLine_=_line;
|
|
_isRequestLineSetted=YES;
|
|
}
|
|
else
|
|
{
|
|
NSString* _key=nil;
|
|
NSString* _value=nil;
|
|
NSArray* _newValue=nil;
|
|
NSArray* _prevValue=nil;
|
|
NSRange _keyRange=[_line rangeOfString:@":"];
|
|
if (_keyRange.length<=0)
|
|
{
|
|
_key=_line;
|
|
NSDebugMLLog(@"low",@"key:%@",_key);
|
|
_value=[NSString string];
|
|
}
|
|
else
|
|
{
|
|
_key=[_line substringToIndex:_keyRange.location];
|
|
NSDebugMLLog(@"low",@"key:%@",_key);
|
|
_key=[[_key stringByTrimmingSpaces] lowercaseString];
|
|
if (_keyRange.location+1<[_line length])
|
|
{
|
|
_value=[_line substringFromIndex:_keyRange.location+1];
|
|
_value=[_value stringByTrimmingSpaces];
|
|
}
|
|
else
|
|
_value=[NSString string];
|
|
NSDebugMLLog(@"low",@"_value:%@",_value);
|
|
};
|
|
NSDebugMLLog(@"low",@"key:%@ value:%@",_key,_value);
|
|
if ([_key isEqualToString:GSWHTTPHeader_ContentLength])
|
|
contentLength=[_value intValue];
|
|
else if ([_key isEqualToString:GSWHTTPHeader_Method[GSWNAMES_INDEX]]
|
|
|| [_key isEqualToString:GSWHTTPHeader_Method[WONAMES_INDEX]])
|
|
{
|
|
if ([_value isEqualToString:GSWHTTPHeader_MethodPost])
|
|
_requestMethod=REQUEST_METHOD__POST;
|
|
else if ([_value isEqualToString:GSWHTTPHeader_MethodGet])
|
|
_requestMethod=REQUEST_METHOD__GET;
|
|
else
|
|
{
|
|
NSAssert1(NO,@"Unknown method %@",_value);
|
|
};
|
|
}
|
|
else if ([_key isEqualToString:GSWHTTPHeader_UserAgent])
|
|
_userAgent=_value;
|
|
else if ([_key isEqualToString:GSWHTTPHeader_RemoteAddress[GSWNAMES_INDEX]]
|
|
||[_key isEqualToString:GSWHTTPHeader_RemoteAddress[WONAMES_INDEX]])
|
|
_remoteAddr=_value;
|
|
if ([_key isEqualToString:GSWHTTPHeader_AdaptorVersion[GSWNAMES_INDEX]]
|
|
|| [_key isEqualToString:GSWHTTPHeader_ServerName[GSWNAMES_INDEX]])
|
|
requestNamingConv=GSWNAMES_INDEX;
|
|
else if ([_key isEqualToString:GSWHTTPHeader_AdaptorVersion[WONAMES_INDEX]]
|
|
|| [_key isEqualToString:GSWHTTPHeader_ServerName[WONAMES_INDEX]])
|
|
requestNamingConv=WONAMES_INDEX;
|
|
|
|
_prevValue=[_headers objectForKey:_key];
|
|
NSDebugMLLog(@"low",@"_prevValue:%@",_prevValue);
|
|
if (_prevValue)
|
|
_newValue=[_prevValue arrayByAddingObject:_value];
|
|
else
|
|
_newValue=[NSArray arrayWithObject:_value];
|
|
if (!_headers)
|
|
_headers=[NSMutableDictionary dictionary];
|
|
[_headers setObject:_newValue
|
|
forKey:_key];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
NSDebugMLog(@"_requestMethod=%d",_requestMethod);
|
|
dataBytesNb=[_pendingData length];
|
|
if (_isDataStep)
|
|
{
|
|
if (_requestMethod==REQUEST_METHOD__GET)
|
|
_isAllDataReaden=YES;
|
|
else if (_requestMethod==REQUEST_METHOD__POST)
|
|
_isAllDataReaden=(dataBytesNb>=contentLength);
|
|
};
|
|
if (!_isAllDataReaden)
|
|
{
|
|
_isElapsed=[[NSDate date]compare:maxDate]==NSOrderedDescending;
|
|
if (!_isElapsed)
|
|
{
|
|
usleep(sleepTime);//Is this the good method ? //TODOV
|
|
_isElapsed=[[NSDate date]compare:maxDate]==NSOrderedDescending;
|
|
};
|
|
};
|
|
} while (!_isAllDataReaden && !_isElapsed);
|
|
NSDebugMLog(@"GSWDefaultAdaptor: _userAgent=%@ _remoteAddr=%@ _isAllDataReaden=%s _isElapsed=%s readenBytesNb=%d contentLength=%d dataBytesNb=%d headersBytesNb=%d",
|
|
_userAgent,
|
|
_remoteAddr,
|
|
_isAllDataReaden ? "YES" : "NO",
|
|
_isElapsed ? "YES" : "NO",
|
|
readenBytesNb,
|
|
contentLength,
|
|
dataBytesNb,
|
|
headersBytesNb);
|
|
ok=_isAllDataReaden;
|
|
if (_isAllDataReaden)
|
|
{
|
|
*headers_=[[_headers copy] autorelease];
|
|
if ([_pendingData length]>0)
|
|
*data_=[_pendingData copy];
|
|
else
|
|
*data_=nil;
|
|
}
|
|
else
|
|
{
|
|
*requestLine_=nil;
|
|
*headers_=nil;
|
|
*data_=nil;
|
|
};
|
|
}
|
|
LOGObjectFnStop();
|
|
return ok;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(GSWRequest*)createRequestFromRequestLine:(NSString*)requestLine_
|
|
headers:(NSDictionary*)headers_
|
|
data:(NSData*)data_
|
|
{
|
|
GSWRequest* _request=nil;
|
|
NSArray* _requestLineArray=nil;
|
|
LOGObjectFnStart();
|
|
NSDebugMLog0(@"GSWDefaultAdaptorThread: createRequestFromData");
|
|
_requestLineArray=[requestLine_ componentsSeparatedByString:@" "];
|
|
NSDebugMLLog(@"low",@"requestLine:%@",requestLine_);
|
|
NSDebugMLLog(@"info",@"_requestLineArray:%@",_requestLineArray);
|
|
if ([_requestLineArray count]!=3)
|
|
{
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"bad request first line (elements count != 3)");
|
|
}
|
|
else
|
|
{
|
|
NSString* method=[_requestLineArray objectAtIndex:0];
|
|
NSString* url=[_requestLineArray objectAtIndex:1];
|
|
NSArray* http=[[_requestLineArray objectAtIndex:2] componentsSeparatedByString:@"/"];
|
|
NSDebugMLLog(@"info",@"method=%@",method);
|
|
NSDebugMLLog(@"info",@"url=%@",url);
|
|
NSDebugMLLog(@"info",@"http=%@",http);
|
|
if ([http count]!=2)
|
|
{
|
|
ExceptionRaise0(@"GSWDefaultAdaptorThread",@"bad request first line (HTTP)");
|
|
}
|
|
else
|
|
{
|
|
NSString* httpVersion=[http objectAtIndex:1];
|
|
/* if (isHeaderKeysEqual(method,GSWHTTPHeader_MethodPost))
|
|
{
|
|
*/
|
|
_request=[[[GSWRequest alloc] initWithMethod:method
|
|
uri:url
|
|
httpVersion:httpVersion
|
|
headers:headers_
|
|
content:data_
|
|
userInfo:nil]
|
|
autorelease];
|
|
/* };*/
|
|
};
|
|
};
|
|
LOGObjectFnStop();
|
|
return _request;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
-(void)sendResponse:(GSWResponse*)response
|
|
{
|
|
LOGObjectFnStart();
|
|
[response willSend];
|
|
if (response)
|
|
{
|
|
int headerN=0;
|
|
int headerNForKey=0;
|
|
NSMutableData* responseData=[[NSMutableData new]autorelease];
|
|
NSArray* headerKeys=[response headerKeys];
|
|
NSArray* headersForKey=nil;
|
|
NSString* key=nil;
|
|
NSString* anHeader=nil;
|
|
NSString* head=[NSString stringWithFormat:@"HTTP/%@ %d %@%@\n",
|
|
[response httpVersion],
|
|
[response status],
|
|
GSWHTTPHeader_Response_OK,
|
|
GSWHTTPHeader_Response_HeaderLineEnd[requestNamingConv]];
|
|
/* NSString* cl=[NSString stringWithFormat:@"%@: %d\n",
|
|
GSWHTTPHeader_ContentLength,
|
|
[[response content] length]];
|
|
*/
|
|
NSString* empty=[NSString stringWithString:@"\n"];
|
|
NSDebugMLLog(@"low",@"head:%@",head);
|
|
[responseData appendData:[head dataUsingEncoding:NSASCIIStringEncoding]];
|
|
for(headerN=0;headerN<[headerKeys count];headerN++)
|
|
{
|
|
key=[headerKeys objectAtIndex:headerN];
|
|
headersForKey=[response headersForKey:key];
|
|
for(headerNForKey=0;headerNForKey<[headersForKey count];headerNForKey++)
|
|
{
|
|
anHeader=[NSString stringWithFormat:@"%@: %@\n",
|
|
key,
|
|
[headersForKey objectAtIndex:headerNForKey]];
|
|
[responseData appendData:[anHeader dataUsingEncoding:NSASCIIStringEncoding]];
|
|
NSDebugMLLog(@"low",@"anHeader:%@",anHeader);
|
|
};
|
|
};
|
|
// NSDebugMLLog(@"low",@"cl:%@",cl);
|
|
NSDebugMLLog(@"low",@"empty:%@",empty);
|
|
// [responseData appendData:[cl dataUsingEncoding:NSASCIIStringEncoding]];
|
|
[responseData appendData:[empty dataUsingEncoding:NSASCIIStringEncoding]];
|
|
|
|
[stream writeData:responseData];
|
|
if ([[response content] length]>0)
|
|
{
|
|
[responseData setLength:[[response content] length]];
|
|
[responseData setData:[response content]];
|
|
|
|
NSDebugMLLog(@"low",@"[response content]:%@",[response content]);
|
|
NSDebugMLLog(@"low",@"[[response content] length]=%d",[[response content] length]);
|
|
NSDebugMLLog(@"low",@"Response content String NSASCIIStringEncoding:%@",[[[NSString alloc] initWithData:[response content]
|
|
encoding:NSASCIIStringEncoding]
|
|
autorelease]);
|
|
NSDebugMLLog(@"low",@"Response content String :%@",[[[NSString alloc] initWithData:[response content]
|
|
encoding:NSISOLatin1StringEncoding]
|
|
autorelease]);
|
|
[stream writeData:responseData];
|
|
NSDebugMLog0(@"Response content Written");
|
|
};
|
|
[stream closeFile];
|
|
};
|
|
LOGObjectFnStop();
|
|
};
|
|
|
|
@end
|