{$DEFINE WST_DBG} unit wst_apache_binding; {$mode objfpc}{$H+} interface uses Classes, SysUtils, httpd, apr, apriconv, aprutil; const sWST_ROOT = 'wst'; sSEPARATOR = '/'; sSERVICES_PREFIXE = 'services'; sWSDL = 'WSDL'; sHTTP_BINARY_CONTENT_TYPE = 'application/octet-stream'; sCONTENT_TYPE = 'Content-Type'; function wst_RequestHandler(r: Prequest_rec): Integer; implementation uses base_service_intf, server_service_intf, server_service_imputils, server_service_soap, server_binary_formatter, metadata_repository, metadata_wsdl, DOM, XMLWrite, user_service_intf, user_service_intf_binder, user_service_intf_imp, metadata_service, metadata_service_binder, metadata_service_imp; type TRequestInfo = record Root : string; URI : string; ContentType : string; Buffer : string; Argument : string; end; TResponseInfo = record ContentText : string; ContentType : string; end; procedure SaveStringToFile(const AStr,AFile:string;const AKeepExisting : Boolean); begin with TMemoryStream.Create() do try if AKeepExisting and FileExists(AFile) then begin LoadFromFile(AFile); Position := Size; end; if ( Length(AStr) > 0 ) then Write(AStr[1],Length(AStr)); SaveToFile(AFile); finally Free(); end; end; function ReadBuffer(r : Prequest_rec; out rbuf : string ) : Integer; var argsbuffer : string; rsize, len_read, rpos : Integer; loc_length : Integer; begin rbuf := ''; Result := ap_setup_client_block(r, REQUEST_CHUNKED_ERROR); if ( Result <> OK ) then Exit; if ( ap_should_client_block(r) <> 0 ) then begin SetLength(argsbuffer,HUGE_STRING_LEN); FillChar(argsbuffer[1],Length(argsbuffer),0); rsize := 0; len_read := 0; rpos := 0; loc_length := r^.remaining; SetLength(rbuf, loc_length ); while True do begin len_read := ap_get_client_block(r, @(argsbuffer[1]), Length(argsbuffer)); if ( len_read <= 0 ) then Exit; if ( ( rpos + len_read ) > loc_length ) then rsize := loc_length - rpos else rsize := len_read; Move(argsbuffer[1],rbuf[ ( 1 + rpos ) ], rsize); Inc(rpos,rsize); end; end; end; function ExtractNextPathElement(var AFullPath : string):string; var i : SizeInt; begin Result := ''; if ( Length(AFullPath) > 0 ) then begin while ( Length(AFullPath) > 0 ) and ( AFullPath[1] = sSEPARATOR ) do begin Delete(AFullPath,1,1); end; i := Pos(sSEPARATOR,AFullPath); if ( i < 1 ) then begin Result := AFullPath; AFullPath := ''; end else begin Result := Copy(AFullPath,1,Pred(i)); Delete(AFullPath,1,i); end; end; end; function GetWSDL(const ARepName, ARootAddress: shortstring):string; var strm : TMemoryStream; rep : PServiceRepository; doc :TXMLDocument; i : SizeInt; s : string; begin Result := ''; rep := nil; doc := Nil; i := GetModuleMetadataMngr().IndexOfName(ARepName); if ( i < 0 ) then Exit; strm := TMemoryStream.Create(); try s := GetModuleMetadataMngr().GetRepositoryName(i); GetModuleMetadataMngr().LoadRepositoryName(s,ARootAddress,rep); strm.Clear(); doc := TXMLDocument.Create(); GenerateWSDL(rep,doc); WriteXMLFile(doc,strm); i := strm.Size; if ( i > 0 ) then begin SetLength(Result,i); Move(strm.memory^,Result[1],i); end; finally doc.Free(); strm.Free(); GetModuleMetadataMngr().ClearRepository(rep); end; end; function GenerateWSDLTable(): string; var r : IModuleMetadataMngr; i : Integer; begin r := GetModuleMetadataMngr(); Result := '' + '
'+ 'The following repositories has available. Click on the link to view the corresponding WSDL.
'+ '' + Format('',[sSEPARATOR+sWST_ROOT+sSEPARATOR+sSERVICES_PREFIXE+sSEPARATOR+sWSDL+sSEPARATOR+r.GetRepositoryName(i)])+ r.GetRepositoryName(i) + ''+ ' | ' + '