├── Brook └── brokers │ └── brookfclfcgibroker.pas ├── README.md ├── bbs.lpi ├── bbs.lpr ├── blowcryp.pas ├── brokers.pas ├── change.pas ├── dependencies.txt ├── fevent.pas ├── find.pas ├── forums.pas ├── frslt.pas ├── geoinfo.pas ├── info.pas ├── legal.pas ├── logout.pas ├── main.pas ├── mapping.pas ├── menu.pas ├── myaccnt.pas ├── newpost.pas ├── news.pas ├── newthm.pas ├── posts.pas ├── registerusr.pas ├── synacode.pas ├── upload.pas └── upst.pas /Brook/brokers/brookfclfcgibroker.pas: -------------------------------------------------------------------------------- 1 | (* 2 | Brook framework, FCL FastCGI Broker 3 | 4 | Copyright (C) 2014 Silvio Clecio 5 | 6 | See the file LICENSE.txt, included in this distribution, 7 | for details about the copyright. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | 13 | /// 08.05.14 added mysql conncetion handling 14 | *) 15 | 16 | unit BrookFCLFCGIBroker; 17 | 18 | {$mode objfpc}{$H+} 19 | 20 | interface 21 | 22 | uses 23 | BrookClasses, BrookApplication, BrookMessages, BrookConsts, BrookHttpConsts, 24 | BrookRouter, BrookUtils, BrookHttpDefsBroker, HttpDefs, CustWeb, CustFCGI, 25 | Classes, SysUtils, Variants, FmtBCD, mysql55conn, sqldb; 26 | 27 | type 28 | TBrookFCGIApplication = class; 29 | 30 | { TBrookApplication } 31 | 32 | TBrookApplication = class(TBrookInterfacedObject, IBrookApplication) 33 | private 34 | FApp: TBrookFCGIApplication; 35 | function GetTerminated: Boolean; 36 | public 37 | constructor Create; virtual; 38 | destructor Destroy; override; 39 | function Instance: TObject; 40 | procedure Run; 41 | procedure Terminate; 42 | property Terminated: Boolean read GetTerminated; 43 | end; 44 | 45 | { TBrookFCGIApplication } 46 | 47 | TBrookFCGIApplication = class(TCustomFCGIApplication) 48 | protected 49 | function InitializeWebHandler: TWebHandler; override; 50 | end; 51 | 52 | { TBrookFCGIRequest } 53 | 54 | TBrookFCGIRequest = class(TFCGIRequest) 55 | protected 56 | procedure DeleteTempUploadedFiles; override; 57 | function GetTempUploadFileName( 58 | const {%H-}AName, AFileName: string; {%H-}ASize: Int64): string; override; 59 | function RequestUploadDir: string; override; 60 | procedure InitRequestVars; override; 61 | procedure HandleUnknownEncoding( 62 | const AContentType: string; AStream: TStream); override; 63 | end; 64 | 65 | { TBrookFCGIResponse } 66 | 67 | TBrookFCGIResponse = class(TFCGIResponse) 68 | protected 69 | procedure CollectHeaders(AHeaders: TStrings); override; 70 | end; 71 | 72 | { TBrookFCGIHandler } 73 | 74 | TBrookFCGIHandler = class(TFCGIHandler) 75 | protected 76 | function CreateRequest: TFCGIRequest; override; 77 | function CreateResponse(ARequest: TFCGIRequest): TFCGIResponse; override; 78 | public 79 | procedure HandleRequest(ARequest: TRequest; AResponse: TResponse); override; 80 | procedure ShowRequestException(R: TResponse; E: Exception); override; 81 | end; 82 | 83 | VAR 84 | conn : TMySQL55Connection; 85 | transaction: TSQLTransaction; 86 | 87 | implementation 88 | 89 | { TBrookApplication } 90 | 91 | function TBrookApplication.GetTerminated: Boolean; 92 | begin 93 | Result := FApp.Terminated; 94 | end; 95 | 96 | constructor TBrookApplication.Create; 97 | begin 98 | FApp := TBrookFCGIApplication.Create(nil); 99 | FApp.Initialize; 100 | end; 101 | 102 | destructor TBrookApplication.Destroy; 103 | begin 104 | FApp.Free; 105 | conn.Connected := false; 106 | transaction.free; 107 | conn.free; 108 | inherited Destroy; 109 | end; 110 | 111 | function TBrookApplication.Instance: TObject; 112 | begin 113 | Result := FApp; 114 | end; 115 | 116 | procedure TBrookApplication.Run; 117 | begin 118 | if BrookSettings.Port <> 0 then 119 | FApp.Port := BrookSettings.Port; 120 | 121 | conn := TMySQL55Connection.Create(nil); 122 | transaction := TSQLTransaction.Create(nil); 123 | conn.HostName := 'localhost'; 124 | conn.Password := 'secret'; 125 | conn.UserName := 'bbsworker'; 126 | conn.DatabaseName := 'bbs'; 127 | conn.CharSet := 'utf8'; 128 | conn.Connected := True; 129 | conn.Transaction := transaction; 130 | 131 | FApp.Run; 132 | end; 133 | 134 | procedure TBrookApplication.Terminate; 135 | begin 136 | FApp.Terminate; 137 | end; 138 | 139 | { TBrookFCGIApplication } 140 | 141 | function TBrookFCGIApplication.InitializeWebHandler: TWebHandler; 142 | begin 143 | Result := TBrookFCGIHandler.Create(Self); 144 | end; 145 | 146 | { TBrookFCGIRequest } 147 | 148 | procedure TBrookFCGIRequest.DeleteTempUploadedFiles; 149 | begin 150 | if BrookSettings.DeleteUploadedFiles then 151 | inherited; 152 | end; 153 | 154 | function TBrookFCGIRequest.GetTempUploadFileName( 155 | const AName, AFileName: string; ASize: Int64): string; 156 | begin 157 | if BrookSettings.KeepUploadedNames then 158 | Result := RequestUploadDir + AFileName 159 | else 160 | Result := inherited GetTempUploadFileName(AName, AFileName, ASize); 161 | end; 162 | 163 | function TBrookFCGIRequest.RequestUploadDir: string; 164 | begin 165 | Result := BrookSettings.DirectoryForUploads; 166 | if Result = '' then 167 | Result := GetTempDir; 168 | Result := IncludeTrailingPathDelimiter(Result); 169 | end; 170 | 171 | procedure TBrookFCGIRequest.InitRequestVars; 172 | var 173 | VMethod: ShortString; 174 | begin 175 | VMethod := Method; 176 | if VMethod = ES then 177 | raise Exception.Create(SBrookNoRequestMethodError); 178 | case VMethod of 179 | BROOK_HTTP_REQUEST_METHOD_DELETE, BROOK_HTTP_REQUEST_METHOD_PUT, 180 | BROOK_HTTP_REQUEST_METHOD_PATCH: 181 | begin 182 | InitPostVars; 183 | if HandleGetOnPost then 184 | InitGetVars; 185 | end; 186 | else 187 | inherited; 188 | end; 189 | end; 190 | 191 | procedure TBrookFCGIRequest.HandleUnknownEncoding(const AContentType: string; 192 | AStream: TStream); 193 | begin 194 | if not BrookHandleUnknownEncoding(Self, AContentType, AStream) then 195 | inherited HandleUnknownEncoding(AContentType, AStream); 196 | end; 197 | 198 | { TBrookFCGIResponse } 199 | 200 | procedure TBrookFCGIResponse.CollectHeaders(AHeaders: TStrings); 201 | begin 202 | AHeaders.Add(BROOK_HTTP_HEADER_X_POWERED_BY + HS + 203 | 'Brook framework and FCL-Web.'); 204 | inherited CollectHeaders(AHeaders); 205 | end; 206 | 207 | { TBrookFCGIHandler } 208 | 209 | function TBrookFCGIHandler.CreateRequest: TFCGIRequest; 210 | begin 211 | Result := TBrookFCGIRequest.Create; 212 | if ApplicationURL = ES then 213 | ApplicationURL := TBrookRouter.RootUrl; 214 | end; 215 | 216 | function TBrookFCGIHandler.CreateResponse(ARequest: TFCGIRequest): TFCGIResponse; 217 | begin 218 | Result := TBrookFCGIResponse.Create(ARequest); 219 | end; 220 | 221 | procedure TBrookFCGIHandler.HandleRequest(ARequest: TRequest; AResponse: TResponse); 222 | begin 223 | AResponse.ContentType := BrookFormatContentType; 224 | try 225 | TBrookRouter.Service.Route(ARequest, AResponse); 226 | TBrookFCGIRequest(ARequest).DeleteTempUploadedFiles; 227 | except 228 | on E: Exception do 229 | ShowRequestException(AResponse, E); 230 | end; 231 | end; 232 | 233 | procedure TBrookFCGIHandler.ShowRequestException(R: TResponse; E: Exception); 234 | begin 235 | BrookShowRequestException(Self, R, E); 236 | end; 237 | 238 | initialization 239 | BrookRegisterApp(TBrookApplication.Create); 240 | 241 | end. 242 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EasyBBS 2 | ======= 3 | 4 | BBS System based on Lazarus and Brook Framework 5 | -------------------------------------------------------------------------------- /bbs.lpi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <UseAppBundle Value="False"/> 14 | <ResourceType Value="res"/> 15 | <ActiveWindowIndexAtStart Value="0"/> 16 | </General> 17 | <i18n> 18 | <EnableI18N LFM="False"/> 19 | </i18n> 20 | <VersionInfo> 21 | <UseVersionInfo Value="True"/> 22 | <AutoIncrementBuild Value="True"/> 23 | <MajorVersionNr Value="1"/> 24 | <BuildNr Value="1"/> 25 | <StringTable CompanyName="Berger EDB Service" FileDescription="bbs" InternalName="bbs" LegalCopyright="(c) 2014 Ralph Berger" OriginalFilename="bbs" ProductName="TeamBBS" ProductVersion="BBS"/> 26 | </VersionInfo> 27 | <BuildModes Count="1" Active="Default"> 28 | <Item1 Name="Default" Default="True"/> 29 | </BuildModes> 30 | <PublishOptions> 31 | <Version Value="2"/> 32 | <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> 33 | <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/> 34 | </PublishOptions> 35 | <RunParams> 36 | <local> 37 | <FormatVersion Value="1"/> 38 | </local> 39 | </RunParams> 40 | <RequiredPackages Count="1"> 41 | <Item1> 42 | <PackageName Value="BrookRT"/> 43 | </Item1> 44 | </RequiredPackages> 45 | <Units Count="23"> 46 | <Unit0> 47 | <Filename Value="bbs.lpr"/> 48 | <IsPartOfProject Value="True"/> 49 | <UnitName Value="bbs"/> 50 | <EditorIndex Value="13"/> 51 | <WindowIndex Value="0"/> 52 | <TopLine Value="1"/> 53 | <CursorPos X="31" Y="4"/> 54 | <UsageCount Value="200"/> 55 | <Loaded Value="True"/> 56 | </Unit0> 57 | <Unit1> 58 | <Filename Value="main.pas"/> 59 | <IsPartOfProject Value="True"/> 60 | <UnitName Value="main"/> 61 | <EditorIndex Value="0"/> 62 | <WindowIndex Value="0"/> 63 | <TopLine Value="142"/> 64 | <CursorPos X="23" Y="150"/> 65 | <UsageCount Value="200"/> 66 | <Loaded Value="True"/> 67 | </Unit1> 68 | <Unit2> 69 | <Filename Value="brokers.pas"/> 70 | <IsPartOfProject Value="True"/> 71 | <UnitName Value="Brokers"/> 72 | <IsVisibleTab Value="True"/> 73 | <EditorIndex Value="12"/> 74 | <WindowIndex Value="0"/> 75 | <TopLine Value="1"/> 76 | <CursorPos X="54" Y="23"/> 77 | <UsageCount Value="200"/> 78 | <Loaded Value="True"/> 79 | </Unit2> 80 | <Unit3> 81 | <Filename Value="forums.pas"/> 82 | <IsPartOfProject Value="True"/> 83 | <UnitName Value="forums"/> 84 | <EditorIndex Value="14"/> 85 | <WindowIndex Value="0"/> 86 | <TopLine Value="1"/> 87 | <CursorPos X="24" Y="38"/> 88 | <UsageCount Value="200"/> 89 | <Loaded Value="True"/> 90 | </Unit3> 91 | <Unit4> 92 | <Filename Value="registerusr.pas"/> 93 | <IsPartOfProject Value="True"/> 94 | <UnitName Value="RegisterUsr"/> 95 | <EditorIndex Value="20"/> 96 | <WindowIndex Value="0"/> 97 | <TopLine Value="155"/> 98 | <CursorPos X="1" Y="174"/> 99 | <UsageCount Value="201"/> 100 | <Loaded Value="True"/> 101 | </Unit4> 102 | <Unit5> 103 | <Filename Value="blowcryp.pas"/> 104 | <IsPartOfProject Value="True"/> 105 | <UnitName Value="BlowCryp"/> 106 | <EditorIndex Value="18"/> 107 | <WindowIndex Value="0"/> 108 | <TopLine Value="62"/> 109 | <CursorPos X="72" Y="74"/> 110 | <UsageCount Value="204"/> 111 | <Loaded Value="True"/> 112 | </Unit5> 113 | <Unit6> 114 | <Filename Value="posts.pas"/> 115 | <IsPartOfProject Value="True"/> 116 | <UnitName Value="posts"/> 117 | <EditorIndex Value="16"/> 118 | <WindowIndex Value="0"/> 119 | <TopLine Value="225"/> 120 | <CursorPos X="1" Y="254"/> 121 | <UsageCount Value="200"/> 122 | <Bookmarks Count="1"> 123 | <Item0 X="1" Y="91" ID="7"/> 124 | </Bookmarks> 125 | <Loaded Value="True"/> 126 | </Unit6> 127 | <Unit7> 128 | <Filename Value="mapping.pas"/> 129 | <IsPartOfProject Value="True"/> 130 | <UnitName Value="Mapping"/> 131 | <EditorIndex Value="10"/> 132 | <WindowIndex Value="0"/> 133 | <TopLine Value="154"/> 134 | <CursorPos X="1" Y="157"/> 135 | <UsageCount Value="201"/> 136 | <Loaded Value="True"/> 137 | </Unit7> 138 | <Unit8> 139 | <Filename Value="logout.pas"/> 140 | <IsPartOfProject Value="True"/> 141 | <UnitName Value="Logout"/> 142 | <EditorIndex Value="9"/> 143 | <WindowIndex Value="0"/> 144 | <TopLine Value="3"/> 145 | <CursorPos X="1" Y="47"/> 146 | <UsageCount Value="201"/> 147 | <Loaded Value="True"/> 148 | </Unit8> 149 | <Unit9> 150 | <Filename Value="info.pas"/> 151 | <IsPartOfProject Value="True"/> 152 | <UnitName Value="info"/> 153 | <EditorIndex Value="2"/> 154 | <WindowIndex Value="0"/> 155 | <TopLine Value="1"/> 156 | <CursorPos X="1" Y="2"/> 157 | <UsageCount Value="200"/> 158 | <Loaded Value="True"/> 159 | </Unit9> 160 | <Unit10> 161 | <Filename Value="synacode.pas"/> 162 | <IsPartOfProject Value="True"/> 163 | <UnitName Value="synacode"/> 164 | <EditorIndex Value="19"/> 165 | <WindowIndex Value="0"/> 166 | <TopLine Value="1"/> 167 | <CursorPos X="59" Y="46"/> 168 | <UsageCount Value="201"/> 169 | <Loaded Value="True"/> 170 | </Unit10> 171 | <Unit11> 172 | <Filename Value="myaccnt.pas"/> 173 | <IsPartOfProject Value="True"/> 174 | <UnitName Value="myAccnt"/> 175 | <EditorIndex Value="21"/> 176 | <WindowIndex Value="0"/> 177 | <TopLine Value="11"/> 178 | <CursorPos X="1" Y="30"/> 179 | <UsageCount Value="200"/> 180 | <Loaded Value="True"/> 181 | </Unit11> 182 | <Unit12> 183 | <Filename Value="newthm.pas"/> 184 | <IsPartOfProject Value="True"/> 185 | <UnitName Value="newThm"/> 186 | <EditorIndex Value="15"/> 187 | <WindowIndex Value="0"/> 188 | <TopLine Value="1"/> 189 | <CursorPos X="1" Y="2"/> 190 | <UsageCount Value="200"/> 191 | <Loaded Value="True"/> 192 | </Unit12> 193 | <Unit13> 194 | <Filename Value="newpost.pas"/> 195 | <IsPartOfProject Value="True"/> 196 | <UnitName Value="newPost"/> 197 | <EditorIndex Value="17"/> 198 | <WindowIndex Value="0"/> 199 | <TopLine Value="1"/> 200 | <CursorPos X="1" Y="271"/> 201 | <UsageCount Value="201"/> 202 | <Loaded Value="True"/> 203 | </Unit13> 204 | <Unit14> 205 | <Filename Value="change.pas"/> 206 | <IsPartOfProject Value="True"/> 207 | <UnitName Value="change"/> 208 | <EditorIndex Value="22"/> 209 | <WindowIndex Value="0"/> 210 | <TopLine Value="231"/> 211 | <CursorPos X="1" Y="252"/> 212 | <UsageCount Value="203"/> 213 | <Loaded Value="True"/> 214 | </Unit14> 215 | <Unit15> 216 | <Filename Value="legal.pas"/> 217 | <IsPartOfProject Value="True"/> 218 | <UnitName Value="legal"/> 219 | <EditorIndex Value="8"/> 220 | <WindowIndex Value="0"/> 221 | <TopLine Value="1"/> 222 | <CursorPos X="24" Y="2"/> 223 | <UsageCount Value="200"/> 224 | <Loaded Value="True"/> 225 | </Unit15> 226 | <Unit16> 227 | <Filename Value="fevent.pas"/> 228 | <IsPartOfProject Value="True"/> 229 | <UnitName Value="fevent"/> 230 | <EditorIndex Value="7"/> 231 | <WindowIndex Value="0"/> 232 | <TopLine Value="21"/> 233 | <CursorPos X="11" Y="18"/> 234 | <UsageCount Value="200"/> 235 | <Loaded Value="True"/> 236 | </Unit16> 237 | <Unit17> 238 | <Filename Value="menu.pas"/> 239 | <IsPartOfProject Value="True"/> 240 | <UnitName Value="Menu"/> 241 | <EditorIndex Value="11"/> 242 | <WindowIndex Value="0"/> 243 | <TopLine Value="140"/> 244 | <CursorPos X="43" Y="147"/> 245 | <UsageCount Value="200"/> 246 | <Loaded Value="True"/> 247 | </Unit17> 248 | <Unit18> 249 | <Filename Value="upst.pas"/> 250 | <IsPartOfProject Value="True"/> 251 | <UnitName Value="upst"/> 252 | <EditorIndex Value="6"/> 253 | <WindowIndex Value="0"/> 254 | <TopLine Value="19"/> 255 | <CursorPos X="23" Y="37"/> 256 | <UsageCount Value="153"/> 257 | <Loaded Value="True"/> 258 | </Unit18> 259 | <Unit19> 260 | <Filename Value="find.pas"/> 261 | <IsPartOfProject Value="True"/> 262 | <UnitName Value="find"/> 263 | <EditorIndex Value="3"/> 264 | <WindowIndex Value="0"/> 265 | <TopLine Value="1"/> 266 | <CursorPos X="21" Y="2"/> 267 | <UsageCount Value="117"/> 268 | <Loaded Value="True"/> 269 | </Unit19> 270 | <Unit20> 271 | <Filename Value="frslt.pas"/> 272 | <IsPartOfProject Value="True"/> 273 | <UnitName Value="frslt"/> 274 | <EditorIndex Value="4"/> 275 | <WindowIndex Value="0"/> 276 | <TopLine Value="1"/> 277 | <CursorPos X="21" Y="2"/> 278 | <UsageCount Value="84"/> 279 | <Loaded Value="True"/> 280 | </Unit20> 281 | <Unit21> 282 | <Filename Value="geoinfo.pas"/> 283 | <IsPartOfProject Value="True"/> 284 | <UnitName Value="geoinfo"/> 285 | <EditorIndex Value="1"/> 286 | <WindowIndex Value="0"/> 287 | <TopLine Value="71"/> 288 | <CursorPos X="70" Y="51"/> 289 | <UsageCount Value="31"/> 290 | <Loaded Value="True"/> 291 | </Unit21> 292 | <Unit22> 293 | <Filename Value="news.pas"/> 294 | <IsPartOfProject Value="True"/> 295 | <UnitName Value="news"/> 296 | <EditorIndex Value="5"/> 297 | <WindowIndex Value="0"/> 298 | <TopLine Value="1"/> 299 | <CursorPos X="21" Y="2"/> 300 | <UsageCount Value="27"/> 301 | <Loaded Value="True"/> 302 | </Unit22> 303 | </Units> 304 | </ProjectOptions> 305 | <CompilerOptions> 306 | <Version Value="11"/> 307 | <PathDelim Value="\"/> 308 | <Target> 309 | <Filename Value="cgi1" ApplyConventions="False"/> 310 | </Target> 311 | <SearchPaths> 312 | <IncludeFiles Value="$(ProjOutDir)"/> 313 | </SearchPaths> 314 | <CodeGeneration> 315 | <Optimizations> 316 | <OptimizationLevel Value="2"/> 317 | </Optimizations> 318 | </CodeGeneration> 319 | <Linking> 320 | <Debugging> 321 | <GenerateDebugInfo Value="False"/> 322 | </Debugging> 323 | </Linking> 324 | <Other> 325 | <CompilerMessages> 326 | <MsgFileName Value=""/> 327 | </CompilerMessages> 328 | <CompilerPath Value="$(CompPath)"/> 329 | </Other> 330 | </CompilerOptions> 331 | <Debugging> 332 | <Exceptions Count="3"> 333 | <Item1> 334 | <Name Value="EAbort"/> 335 | </Item1> 336 | <Item2> 337 | <Name Value="ECodetoolError"/> 338 | </Item2> 339 | <Item3> 340 | <Name Value="EFOpenError"/> 341 | </Item3> 342 | </Exceptions> 343 | </Debugging> 344 | <EditorMacros Count="0"/> 345 | </CONFIG> 346 | -------------------------------------------------------------------------------- /bbs.lpr: -------------------------------------------------------------------------------- 1 | program bbs; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | uses 6 | BrookApplication, Brokers, synacode, Mapping, main, forums, RegisterUsr, 7 | posts, Logout, info, myAccnt, newThm, newPost, change, legal, fevent, Menu, 8 | upst, find, frslt, geoinfo, news; 9 | 10 | {$R *.res} 11 | 12 | begin 13 | BrookApp.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /blowcryp.pas: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////// 2 | // funktion : Hilfsunit mit oft gebrauchten komponenten 3 | // Datum : 03.08.2013 4 | // modified : 01.03.2014 5 | // 23.04.2014 BF 2.6.4 -> BF 3.0.0 6 | // 08.05.2014 ip_ntoa & ip_aton change integer to int64 7 | 8 | unit BlowCryp; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses 15 | BrookHTTPConsts, BrookConsts, HTTPDefs, BrookHTTPClient, BrookFCLHTTPClientBroker, 16 | Classes, SysUtils, Variants, FmtBCD, blowfish; 17 | 18 | type 19 | paraType = record // lokal vars for get/post handlers 20 | VSession : string ; 21 | sError: string ; 22 | sTopic : string ; 23 | sID : string ; 24 | sPst : string ; 25 | text1 : string ; 26 | text2 : string ; 27 | sCmd : string; 28 | lastError : string; 29 | userID : integer; 30 | sip : string; // client ip 31 | v_order : String; 32 | v_page : String; 33 | v_rec : String; 34 | v_eof : String; 35 | end; 36 | 37 | sessInfType = record // session record 38 | rid : string; 39 | id : string; 40 | user_id: string; 41 | forum_id: string; 42 | is_active: string; 43 | last_forum: string; 44 | browser: string; // client browser 45 | sip : string; // client ip 46 | sLat : string; 47 | sLong : string; 48 | latitude: string; 49 | longitude: string; 50 | accuracy : string; 51 | forwarded_for : string; // footer infos start 52 | v_order : String; 53 | v_page : String; 54 | v_rec : String; 55 | v_eof : String; 56 | viewonline : string; 57 | autologin : string; 58 | admin : string; 59 | lastsearch : string; 60 | lastlogin : String; 61 | last_post_cnt : String; // footer infos end 62 | login : string; 63 | logout : string; 64 | end; 65 | 66 | 67 | function ip_ntoa(nip: int64):string; 68 | function ip_aton(sip: string):int64; 69 | procedure GetIPLatLon( CONST sURL_sip:String; VAR sLat, sLong:STRING ); 70 | function sUpdate(const s1,s2,s3:String):String; 71 | function encrypt(inStrg: string): string; 72 | function decrypt(inStrg: string): string; 73 | procedure codeSessionID( VAR sesnRec: sessInfType ); 74 | function decodeSessionID(VAR myPara: ParaType ):integer; 75 | function isSessionValid( VAR myPara: ParaType):boolean; 76 | FUNCTION SecuredStr(CONST S : STRING) : STRING; 77 | Function sPlus( sIn: String ) : String; 78 | Function sMinus( sIn: String ) : String; 79 | function StrToHex(const value:string):string; 80 | function StripHTML(S: string): string; 81 | function iif( bPara: Boolean; sTrue, sFalse:String):String; 82 | 83 | implementation 84 | 85 | 86 | function StripHTML(S: string): string; 87 | var 88 | TagBegin, TagEnd, TagLength: integer; 89 | begin 90 | TagBegin := Pos( '<', S); // search position of first < 91 | 92 | while (TagBegin > 0) do begin // while there is a < in S 93 | TagEnd := Pos('>', S); // find the matching > 94 | TagLength := TagEnd - TagBegin + 1; 95 | Delete(S, TagBegin, TagLength); // delete the tag 96 | TagBegin:= Pos( '<', S); // search for next < 97 | end; 98 | 99 | Result := S; // give the result 100 | end; 101 | 102 | 103 | Function sPlus( sIn: String ) : String; 104 | var 105 | i: integer; 106 | begin 107 | try 108 | i := StrToInt( sIn ); 109 | except 110 | on e: Exception do i := 0; 111 | end; 112 | 113 | sPlus := IntToStr( i+1 ); 114 | end; 115 | 116 | Function sMinus( sIn: String ) : String; 117 | var 118 | i: integer; 119 | begin 120 | try 121 | i := StrToInt( sIn ); 122 | except 123 | on e: Exception do i := 0; 124 | end; 125 | 126 | if i > 1 then 127 | sMinus := IntToStr( i-1 ) 128 | else 129 | sMinus := '0'; 130 | 131 | end; 132 | 133 | function iif( bPara: Boolean; sTrue, sFalse:String):String; 134 | begin 135 | if bPara then 136 | iif := sTrue 137 | else 138 | iif := sFalse; 139 | end; 140 | 141 | function ip_ntoa(nip: int64):string; 142 | var 143 | o1,o2,o3,o4 : int64; 144 | begin 145 | o1 := ( nip DIV 16777216 ) MOD 256; 146 | o2 := ( nip DIV 65536 ) MOD 256; 147 | o3 := ( nip DIV 256 ) MOD 256; 148 | o4 := ( nip ) MOD 256; 149 | ip_ntoa := IntToStr(o1) + '.' + 150 | IntToStr(o2) + '.' + 151 | IntToStr(o3) + '.' + 152 | IntToStr(o4) ; 153 | end; 154 | 155 | 156 | function ip_aton(sip: string):int64; 157 | var 158 | o1,o2,o3,o4 : int64; 159 | integer_ip : int64; 160 | Oktett : TStringList; 161 | 162 | begin 163 | Oktett := TStringList.Create; 164 | Oktett.Delimiter := '.'; 165 | Oktett.DelimitedText := sip; 166 | 167 | try 168 | o1 := StrToInt( Oktett[0] ); 169 | o2 := StrToInt( Oktett[1] ); 170 | o3 := StrToInt( Oktett[2] ); 171 | o4 := StrToInt( Oktett[3] ); 172 | if ( o1 < 0 ) or ( o1 > 255 ) or 173 | ( o2 < 0 ) or ( o2 > 255 ) or 174 | ( o3 < 0 ) or ( o3 > 255 ) or 175 | ( o4 < 0 ) or ( o4 > 255 ) then raise Exception.Create('Oktett Fehler: Eingabe < 0 oder > 255'); 176 | integer_ip := 16777216 * o1 177 | + 65536 * o2 178 | + 256 * o3 179 | + o4 ; 180 | except 181 | on e: Exception do 182 | begin 183 | integer_ip := 0; 184 | // ShowMessage('Falsches IP Format: ' + e.Message ); 185 | end; 186 | end; 187 | Oktett.Free; 188 | ip_aton := integer_ip; 189 | end; 190 | 191 | function iTime():integer; 192 | var 193 | Hour, Min, Sec, MSec, Y, M, D : Word; 194 | begin 195 | DecodeTime(now(), Hour, Min, Sec, MSec); 196 | DecodeDate(now(), Y, M, D); 197 | iTime := Min + 60 * Hour + 1440 * D; 198 | end; 199 | 200 | 201 | // build session id based on 202 | // user IP & user.iduser + now() 203 | procedure codeSessionID( VAR sesnRec: sessInfType ); 204 | begin 205 | sesnRec.id := encrypt( 206 | inttostr(ip_aton( sesnRec.sip ))+ 207 | '|' + sesnRec.user_id + 208 | '|' + inttostr( iTime ) ) ; 209 | end; 210 | 211 | 212 | 213 | function decodeSessionID( VAR myPara: ParaType ):integer; 214 | var 215 | i : integer; 216 | sInfo : TStringList; 217 | 218 | 219 | begin 220 | // exit on empty sesion string 221 | if myPara.VSession = '' then 222 | begin 223 | myPara.userID := 0; 224 | decodeSessionID := 0; 225 | exit; 226 | end; 227 | 228 | // parse session string 229 | sInfo := TStringList.Create; 230 | sInfo.Delimiter := '|'; 231 | sInfo.DelimitedText := decrypt(myPara.VSession); 232 | 233 | // handle special ip '0.0.0.1' ( used in register mail ) 234 | if sInfo[0] = '1' then sInfo[0] := inttostr(ip_aton( myPara.sIP )); 235 | 236 | // check ip 237 | if sInfo[0] <> inttostr(ip_aton( myPara.sIP )) then 238 | begin 239 | // error on ip diff 240 | myPara.userID := 0; 241 | decodeSessionID := -1; 242 | sInfo.Free; 243 | exit; 244 | end; 245 | 246 | // nothing is granted ! 247 | try 248 | myPara.userID := strtoint( sInfo[1] ); 249 | i := strtoint( sInfo[2] ); 250 | except 251 | myPara.userID := 0; 252 | i := 0; 253 | end; 254 | 255 | decodeSessionID := itime() - i; // calc sesn age( mins) 256 | sInfo.Free; 257 | end; 258 | 259 | // check session 260 | // function isSessionValid( VSession: string; VAR sError:String; VAR userID:integer ):boolean; 261 | function isSessionValid( VAR myPara: ParaType):boolean; 262 | VAR 263 | ttl:integer ; // time to life 264 | begin 265 | isSessionValid := FALSE; 266 | IF myPara.VSession <> '' then // exit on empty vSession 267 | begin 268 | ttl := decodeSessionID(myPara ); 269 | if ttl > 60 then // timeout in minutes 270 | begin 271 | myPara.LastError := 'Session abgelaufen.'; 272 | exit; 273 | end; 274 | if ttl < 0 then // different ip 275 | begin 276 | myPara.LastError := 'Session ungültig.'; 277 | exit; 278 | end; 279 | isSessionValid := true; // set session flag 280 | end; 281 | 282 | end; 283 | 284 | 285 | /// replaceString wrapper 286 | function sUpdate (const s1,s2,s3:String):String; 287 | begin 288 | result:= StringReplace(s1, s2, s3, [rfReplaceAll]); 289 | end; 290 | 291 | 292 | // procedure GetIPLatLon( CONST sip:String; VAR sLat, sLong:STRING ); 293 | // procedure GetIPLatLon( CONST conn: TMySQL55Connection; sip:String; VAR sLat, sLong:STRING ); 294 | procedure GetIPLatLon( CONST sURL_sip:String; VAR sLat, sLong:STRING ); 295 | 296 | var 297 | VClient: TBrookHTTPClient; 298 | VHttp : TBrookHTTPDef = nil; 299 | sInfo : TStringList; 300 | 301 | begin 302 | VClient := TBrookHTTPClient.Create('fclweb'); 303 | sInfo := TStringList.Create; 304 | sInfo.Delimiter := ','; 305 | 306 | try 307 | VClient.Prepare(VHttp); 308 | VHttp.Method := 'GET'; 309 | VHttp.Url := sURL_sip ; 310 | VClient.Request(VHttp); 311 | VHttp.Document.Position := 0; 312 | sInfo.LoadFromStream(VHttp.Document); 313 | 314 | // cut down JSON string 315 | // sTest := '{"ip":"109.128.12.96","country_code":"BE","region_code":"11","city":"Brussels","zipcode":"", 316 | // "latitude":50.8333 ,"longitude":4.3333 ,"region_name":"Brussels Hoofdstedelijk Gewest","country_name":"Belgium"}'; 317 | sInfo.DelimitedText := sUpdate( sUpdate( sUpdate(sInfo.Text , '{', '' ), '}', '' ), '"', '' ); 318 | sLat := sUpdate( sInfo[5], 'latitude:', '' ); 319 | sLong := sUpdate( sInfo[6], 'longitude:', '' ); 320 | 321 | except 322 | // no answer from service 323 | on e: Exception do 324 | begin 325 | sLat := '0'; 326 | sLong := '0'; 327 | end; 328 | end; 329 | 330 | VHttp.Free; 331 | VClient.Free; 332 | sInfo.Free; 333 | 334 | 335 | 336 | end; 337 | 338 | FUNCTION SecuredStr(CONST S : STRING) : STRING; 339 | var 340 | sTemp : string; 341 | flag : boolean; 342 | 343 | BEGIN 344 | // silent correction 345 | sTemp := s; 346 | sTemp := sUpdate(sTemp, '''', ''); // remove quotes 347 | sTemp := sUpdate(sTemp, '"',''); // remove DQ 348 | SecuredStr:= sUpdate(sTemp, ';',''); // remove Semicolon 349 | 350 | // punisher action: return empty string 351 | sTemp := UpperCase(sTemp); 352 | flag := Pos('AND', sTemp) > 0 ; 353 | flag := flag OR ( Pos('DROP', sTemp) > 0 ); 354 | flag := flag OR ( Pos('OR 1', sTemp) > 0 ); 355 | flag := flag OR ( Pos('LIKE', sTemp) > 0 ); 356 | flag := flag OR ( Pos('WHERE', sTemp)> 0 ); 357 | flag := flag OR ( Pos('CREATE', sTemp)> 0 ); 358 | if flag then SecuredStr:= ''; 359 | 360 | END; 361 | 362 | 363 | 364 | {************************************************************************** 365 | * NAME: StringToHexStr 366 | * DESC: Konvertiert einen String in eine hexadezimale Darstellung 367 | *************************************************************************} 368 | function StrToHex(const value:string):string; 369 | begin 370 | SetLength(Result, Length(value)*2); // es wird doppelter Platz benötigt 371 | if Length(value) > 0 then 372 | BinToHex(PChar(value), PChar(Result), Length(value)); 373 | end; 374 | 375 | 376 | {************************************************************************** 377 | * NAME: HexStrToString 378 | * DESC: Dekodiert einen hexadezimalen String 379 | *************************************************************************} 380 | function HexToStr(const value:string):string; 381 | begin 382 | SetLength(Result, Length(value) div 2); // es wird halber Platz benötigt 383 | if Length(value) > 0 then 384 | HexToBin(PChar(value), PChar(Result), Length(value)); 385 | end; 386 | 387 | 388 | 389 | /// blowfish crypt functions 390 | function encrypt(inStrg: string): string; 391 | var 392 | s1: TStringStream; 393 | bf: TBlowfishEncryptStream; 394 | 395 | begin 396 | if inStrg ='' then exit; 397 | s1:=TStringStream.Create(''); // make sure destination stream is blank 398 | bf:=TBlowfishEncryptStream.Create('Bahn#1hof', s1); // writes to destination stream 399 | bf.writeAnsiString( inStrg ); 400 | bf.free; 401 | result:= StrToHex ( s1.datastring ) ; 402 | s1.free; 403 | 404 | end; 405 | 406 | function decrypt(inStrg: string): string; 407 | var 408 | s2: TStringStream; 409 | bf: TBlowfishDecryptStream; 410 | 411 | begin 412 | if inStrg ='' then exit; 413 | s2:=TStringStream.Create( HexToStr(inStrg) ); // fill stream 414 | bf:=TBlowfishDecryptStream.Create('Bahn#1hof', s2); // create blowfish stream 415 | result:= bf.readAnsiString ; // copy stream contents to destination 416 | bf.free; 417 | s2.free; 418 | 419 | end; 420 | 421 | 422 | end. 423 | 424 | 425 | 426 | -------------------------------------------------------------------------------- /brokers.pas: -------------------------------------------------------------------------------- 1 | unit Brokers; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | BrookFCLFCGIBroker, SysUtils, BrookUtils, BrookHTTPConsts; 9 | 10 | implementation 11 | const 12 | HTML_TPL = '<html><head><title>%s

%s


%s%s'; 13 | 14 | function HTML(const ATitle, AError, AMsg, ATrace: string): string; 15 | begin 16 | Result := Format(HTML_TPL, [ATitle, AError, AMsg, ATrace]); 17 | end; 18 | 19 | initialization 20 | BrookSettings.Charset := BROOK_HTTP_CHARSET_UTF_8; 21 | BrookSettings.Page404 := HTML('Page not found', '404 - Page not found', 'Click here to go to home page ...', ''); 22 | BrookSettings.Page500 := HTML('Internal server error','500 - Internal server error', 'Error: @error','

Trace: @trace'); 23 | BrookSettings.DirectoryForUploads := 'C:\Apache22\fcgi-bin\upld'; 24 | end. 25 | 26 | -------------------------------------------------------------------------------- /change.pas: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // file : change.pas 3 | // erstellt : 01.03.14 4 | // called via: 'cgi1/change?B2=xx&ID=xx&sesn=xx&Pst=xx 5 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 6 | 7 | 8 | unit change; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses 15 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, 16 | Variants, FmtBCD, sqldb, mapping, blowcryp, menu; 17 | 18 | 19 | type 20 | TChange = class(TBrookAction) 21 | public 22 | procedure Get; override; 23 | procedure Post; override; 24 | procedure HandlePst( VAR myPara: ParaType); 25 | procedure InfoPstDelete( VAR myPara: ParaType); 26 | procedure EditTpc ( VAR myPara: ParaType ); 27 | procedure PstDelete( VAR myPara: ParaType ); 28 | procedure Pst_Save ( VAR myPara: ParaType ); 29 | procedure Tpc_Save ( VAR myPara: ParaType ); 30 | end; 31 | 32 | implementation 33 | 34 | 35 | //////////////////////////////////////////////////////////// 36 | // show post form in edit mode 37 | // 38 | procedure TChange.HandlePst( VAR myPara: ParaType); 39 | VAR 40 | memFrm : ForInfType ; 41 | memTpc : TopInfType ; 42 | PstFrm : PstInfType ; 43 | usrFrm1: usrInfType ; 44 | mySessn: sessInfType; 45 | 46 | 47 | begin 48 | 49 | // read session record 50 | paraTypeInit('change?', myPara ); 51 | mySessn.id := mypara.VSession; 52 | sesn_Read( conn, mySessn ); 53 | sesn_copy_para( mySessn, myPara ); 54 | 55 | 56 | // read posts record 57 | PstFrm.id := myPara.sID; 58 | posts_read( BrookFCLFCGIBroker.conn, PstFrm ); 59 | if PstFrm.id = '' then 60 | begin 61 | Render(err_page, ['Posting ID fehlt.']); 62 | exit; 63 | end; 64 | 65 | // read related records 66 | memTpc.id := PstFrm.topic_id; 67 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 68 | ReadUsr( BrookFCLFCGIBroker.conn, 'WHERE iduser=' + PstFrm.user_id, usrFrm1 ); 69 | ReadForum ( BrookFCLFCGIBroker.conn, 'where id=' + PstFrm.forum_id, memFrm ); 70 | 71 | 72 | // start render 73 | myPara.sID := memTpc.forum_id; 74 | myPara.sPst := memFrm.fName; 75 | myPara.sTopic := memTpc.title; 76 | 77 | Render('bbs_editpst.html', [make_Header_APosts( myPara ), // Header Menu 78 | showUsrImage(usrFrm1), // UsrImage(conn, usrFrm1.iduser), 79 | showUsrInfo(usrFrm1), // Usr Info 80 | usrFrm1.Name, // Column 2 Usr Name 81 | memFrm.fName, // C2 Topic Header 82 | PstFrm.post_subject, // C2 Theme - editable 83 | PstFrm.post_text, // C2 Text - editable 84 | myPara.VSession, 85 | PstFrm.id, 86 | make_Footer( BrookFCLFCGIBroker.conn, mypara ) ]); 87 | 88 | end; 89 | 90 | procedure TChange.InfoPstDelete( VAR myPara: ParaType); 91 | VAR 92 | sBody : String; 93 | PstFrm : PstInfType; 94 | memFrm : ForInfType ; 95 | memTpc : TopInfType ; 96 | usrFrm1: usrInfType; 97 | mySessn: sessInfType; 98 | 99 | 100 | begin 101 | 102 | // read session record 103 | paraTypeInit('change?', myPara ); 104 | mySessn.id := mypara.VSession; 105 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 106 | sesn_copy_para( mySessn, myPara ); 107 | 108 | // read posts record 109 | PstFrm.id := myPara.sID; 110 | posts_read( BrookFCLFCGIBroker.conn, PstFrm ); 111 | if PstFrm.id = '' then 112 | begin 113 | Render(err_page, ['Posting ID fehlt.']); 114 | exit; 115 | end; 116 | 117 | // read related recs 118 | memTpc.id:= PstFrm.topic_id; 119 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 120 | ReadUsr( BrookFCLFCGIBroker.conn, 'WHERE iduser='+PstFrm.user_id, usrFrm1 ); 121 | ReadForum ( BrookFCLFCGIBroker.conn, 'where id=' + PstFrm.forum_id, memFrm ); 122 | 123 | // delete confirm body 124 | sBody := sUpdate( delpst,'%%1', usrFrm1.Name ); 125 | sBody := sUpdate( sBody, '%%2', PstFrm.post_time ); 126 | sBody := sUpdate( sBody, '%%3', PstFrm.post_text ); 127 | sBody := sUpdate( sBody, '%%4', PstFrm.id ); 128 | sBody := sUpdate( sBody, '%%5', myPara.VSession ); 129 | sBody := sUpdate( sBody, '%%6', showUsrImage(usrFrm1)); 130 | sBody := sUpdate( sBody, '%%7', showUsrInfo(usrFrm1)); 131 | 132 | // start render 133 | mypara.sCmd := '0'; // '0' no navi btns 134 | myPara.sID := memTpc.forum_id; 135 | myPara.sPst := memFrm.fName; 136 | myPara.sTopic := memTpc.title; 137 | 138 | Render('bbs_thread.html', [make_Header_APosts( myPara ), // header 139 | sBody, // topic record 140 | make_Footer(BrookFCLFCGIBroker.conn,mypara)] ); // footer 141 | 142 | end; 143 | 144 | procedure TChange.EditTpc( VAR myPara: ParaType); 145 | VAR 146 | memFrm : ForInfType ; 147 | memTpc : TopInfType ; 148 | usrFrm1: usrInfType ; 149 | 150 | 151 | begin 152 | 153 | 154 | // copy to record 155 | memTpc.id:= myPara.sID; 156 | Topic_Read( conn, memTpc ); 157 | ReadForum ( conn, 'where id=' + memTpc.forum_id, memFrm ); 158 | ReadUsr ( conn, 'where iduser=' + memTpc.poster, usrFrm1 ); 159 | 160 | // start render 161 | mypara.sCmd := '0'; // '0' no navi btns 162 | myPara.sID := memTpc.forum_id; 163 | myPara.sPst := memFrm.fName; 164 | myPara.sTopic := memTpc.title; 165 | Render('bbs_edithm.html', [ make_Header_APosts( myPara ), // header 166 | showUsrImage(usrFrm1), // Usr Image 167 | showUsrInfo(usrFrm1), // Usr Info 168 | usrFrm1.Name, // Column2 Usr Name 169 | memFrm.fName, // Column2 Forum Name 170 | memTpc.title, // Column2 Thema Header - editable 171 | memTpc.topic_text, // Column2 Thema Text - editable 172 | myPara.VSession, // Hidden Session ID 173 | memTpc.id, // Hidden Topic ID 174 | make_Footer(BrookFCLFCGIBroker.conn ,mypara) ]); // footer w/o navi 175 | 176 | end; 177 | 178 | /////////////////////////////////////////////////////// 179 | // procedure : TChange.Get; 180 | // description : Get Handler for bbs_thread.html form 181 | // Dispatch to procs 182 | 183 | procedure TChange.Get; 184 | VAR 185 | mode : Integer; 186 | myPara : ParaType; 187 | 188 | begin 189 | 190 | // read paras 191 | myPara.VSession := Params.Values['sesn']; 192 | myPara.sTopic := Params.Values['Tpc']; 193 | myPara.sPst := Params.Values['Pst']; 194 | myPara.sID := Params.Values['ID']; 195 | myPara.sCmd := Params.Values['B2']; 196 | myPara.sCmd += Params.Values['B3']; // form submits B2 or B3 197 | // check paras 198 | mypara.sip:= TheRequest.RemoteAddress; 199 | if NOT isSessionValid( mypara ) then 200 | begin 201 | Render(err_page, [myPara.LastError]); 202 | exit; 203 | end; 204 | 205 | case myPara.sCmd of 206 | 'chgtpc' : mode := 1; // change a topic 207 | 'chngpst' : mode := 2; // change a posting 208 | 'deltpst' : mode := 3; // delete a posting 209 | else 210 | begin 211 | Render(err_page, ['Funktion fehlt oder unbekannt: ' + myPara.sCmd ]); 212 | exit; 213 | end; 214 | end; 215 | 216 | if (mode = 1) AND (myPara.sTopic = '') then 217 | begin 218 | Render(err_page, ['Topic ID fehlt.']); 219 | exit; 220 | end; 221 | 222 | if (mode = 2) AND (myPara.sPst = '') then 223 | begin 224 | Render(err_page, ['Nachricht ID fehlt.']); 225 | exit; 226 | end; 227 | 228 | if (mode = 3) AND (myPara.sPst = '') then 229 | begin 230 | Render(err_page, ['Nachricht ID fehlt.']); 231 | exit; 232 | end; 233 | 234 | /// call info procedures - last chance for user to abort 235 | case mode of 236 | 1 : EditTpc(myPara) ; 237 | 2 : HandlePst(myPara) ; 238 | 3 : InfoPstDelete(myPara); 239 | end; 240 | 241 | end; 242 | 243 | /// DELETE Button Action 244 | procedure TChange.PstDelete( VAR myPara: ParaType); 245 | VAR 246 | PstFrm : PstInfType; 247 | usrFrm1: usrInfType; 248 | memFrm : ForInfType ; 249 | memTpc : TopInfType ; 250 | 251 | begin 252 | 253 | // read posts to rescue topic_id, forum_id and user_id 254 | PstFrm.id := myPara.sID; 255 | posts_read( BrookFCLFCGIBroker.conn, PstFrm ); 256 | if PstFrm.id = '' then 257 | begin 258 | Render(err_page, ['Nachricht fehlt.']); 259 | exit; 260 | end; 261 | 262 | // read related recs 263 | memTpc.id := PstFrm.topic_id; 264 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 265 | ReadForum ( BrookFCLFCGIBroker.conn, 'where id=' + PstFrm.forum_id, memFrm ); 266 | ReadUsr(BrookFCLFCGIBroker.conn, 'where iduser=' + PstFrm.user_id, usrFrm1 ); 267 | 268 | // delete posting 269 | myPara.LastError := posts_Delete( BrookFCLFCGIBroker.conn, PstFrm.id ); 270 | if myPara.LastError <> '' then 271 | begin 272 | Render(err_page, ['Fehler beim Löschen der Nachricht: ' + myPara.LastError]); 273 | exit; 274 | end; 275 | 276 | // refresh counters 277 | // update topic 278 | memTpc.views := sPlus( memTpc.views ); 279 | memTpc.replies := sMinus( memTpc.replies ); 280 | memTpc.replies_real := sMinus( memTpc.replies_real ); 281 | memTpc.last_poster_id := PstFrm.user_id ; 282 | memTpc.last_poster_name := usrFrm1.Name; 283 | memTpc.last_view_time := DateTimeToStr(now) ; 284 | 285 | myPara.LastError := Topic_Update( BrookFCLFCGIBroker.conn, memTpc ); 286 | if myPara.LastError <> '' then 287 | begin 288 | Render(err_page, ['Fehler beim Aktualisieren des Themas: ' + myPara.LastError]); 289 | exit; 290 | end; 291 | 292 | // update forum 293 | memFrm.posts := sMinus( memFrm.posts ); 294 | memFrm.last_poster_id := usrFrm1.iduser ; 295 | memFrm.last_poster_name := usrFrm1.Name; 296 | myPara.LastError := Upd_Forum( BrookFCLFCGIBroker.conn, memFrm ); 297 | if myPara.LastError <> '' then 298 | begin 299 | Render(err_page, ['Fehler beim Aktualisieren des Forums: ' +myPara.LastError]); 300 | exit; 301 | end; 302 | 303 | redirect ('topic?ID=' + PstFrm.forum_id + '&Tpc=' + PstFrm.topic_id + '&sesn=' + myPara.VSession, 302); 304 | end; 305 | 306 | procedure TChange.Pst_Save ( VAR myPara: ParaType); 307 | VAR 308 | PstFrm : PstInfType; 309 | usrFrm1: usrInfType; 310 | memFrm : ForInfType ; 311 | memTpc : TopInfType ; 312 | 313 | 314 | begin 315 | 316 | // read posts record 317 | PstFrm.id := myPara.sID; 318 | posts_read( BrookFCLFCGIBroker.conn, PstFrm ); 319 | if PstFrm.id = '' then 320 | begin 321 | Render(err_page, ['Posting ID zum Update fehlt.' + myPara.sID + '--' ]); 322 | exit; 323 | end; 324 | 325 | // read related recs 326 | memTpc.id := PstFrm.topic_id; 327 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 328 | ReadUsr( BrookFCLFCGIBroker.conn, 'WHERE iduser=' + PstFrm.user_id, usrFrm1 ); 329 | ReadForum ( BrookFCLFCGIBroker.conn, 'where id=' + PstFrm.forum_id, memFrm ); 330 | 331 | // update posting 332 | PstFrm.post_subject := myPara.text1; 333 | PstFrm.post_text := myPara.text2; 334 | PstFrm.post_edit_count := sPlus( PstFrm.post_edit_count ); 335 | PstFrm.post_edit_time := DateTimeToStr(now) ; 336 | PstFrm.post_edit_reason := myPara.sCmd; 337 | PstFrm.post_edit_user := usrFrm1.iduser; 338 | PstFrm.post_alpha := LeftStr( StripHTML( PstFrm.post_text) , 255 ); 339 | PstFrm.post_size := IntToStr( Length ( PstFrm.post_text) ); 340 | myPara.lastError := posts_Update( BrookFCLFCGIBroker.conn, PstFrm ); 341 | if myPara.lastError <> '' then 342 | begin 343 | Render(err_page, ['Fehler beim Aktualisieren der Nachricht: ' + myPara.lastError]); 344 | exit; 345 | end; 346 | 347 | // refresh counters 348 | // update topic 349 | memTpc.views := sPlus( memTpc.views ); 350 | memTpc.last_poster_id := PstFrm.post_edit_user ; 351 | memTpc.last_poster_name := usrFrm1.Name; 352 | memTpc.last_view_time := DateTimeToStr(now) ; 353 | 354 | myPara.lastError := Topic_Update( BrookFCLFCGIBroker.conn, memTpc ); 355 | if myPara.lastError <> '' then 356 | begin 357 | Render(err_page, ['Fehler beim Aktualisieren des Themas: ' + myPara.lastError ]); 358 | exit; 359 | end; 360 | 361 | // update forum 362 | memFrm.last_poster_id := PstFrm.post_edit_user ; 363 | memFrm.last_poster_name := usrFrm1.Name; 364 | myPara.lastError := Upd_Forum( BrookFCLFCGIBroker.conn, memFrm ); 365 | if myPara.lastError <> '' then 366 | begin 367 | Render(err_page, ['Fehler beim Aktualisieren des Forums: ' + myPara.lastError]); 368 | exit; 369 | end; 370 | 371 | redirect ('topic?ID=' + PstFrm.forum_id + '&Tpc=' + PstFrm.topic_id + '&sesn=' + myPara.VSession, 302); 372 | end; 373 | 374 | 375 | /////////////////////////////////////////// 376 | // Save changes to topic 377 | // Save old topic to log 378 | // Update forum's last use 379 | // finish with jump to post page 380 | procedure TChange.Tpc_Save ( VAR myPara: ParaType); 381 | VAR 382 | sTmp : string; 383 | memTpc : TopInfType ; 384 | 385 | 386 | begin 387 | 388 | // read topic 389 | memTpc.id := myPara.sTopic; 390 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 391 | if memTpc.id = '' then 392 | begin 393 | Render(err_page, ['Fehler beim Lesen des Themas: ' + myPara.sTopic]); 394 | exit; 395 | end; 396 | 397 | // update topic 398 | memTpc.views := sPlus( memTpc.views ); 399 | memTpc.title := myPara.text1; 400 | memTpc.topic_text := myPara.text2; 401 | memTpc.last_view_time := DateTimeToStr(now); 402 | memTpc.last_post_time := memTpc.last_view_time; 403 | 404 | // save topic 405 | sTmp := Topic_Update( BrookFCLFCGIBroker.conn, memTpc ); 406 | if sTmp <> '' then 407 | begin 408 | Render(err_page, ['Fehler beim Aktualisieren des Themas: ' + sTmp]); 409 | exit; 410 | end; 411 | 412 | // go to post page 413 | redirect ('topic?ID=' + memTpc.forum_id + '&Tpc=' + memTpc.id + '&sesn=' + myPara.VSession, 302); 414 | 415 | 416 | end; 417 | 418 | procedure TChange.Post; 419 | VAR 420 | myPara : ParaType; 421 | 422 | begin 423 | 424 | // check paras 425 | myPara.VSession := Fields.Values['sesn']; 426 | myPara.sTopic := Fields.Values['Tpc']; 427 | myPara.sPst := Fields.Values['Pst']; 428 | myPara.sID := Fields.Values['ID']; 429 | myPara.text1 := Fields.Values['tpc_name']; 430 | myPara.text2 := Fields.Values['S1']; 431 | myPara.sCmd := Fields.Values['B2']; 432 | myPara.sCmd += Fields.Values['B3']; 433 | myPara.sCmd += Fields.Values['B4']; // form post Button B2,B3 or B4 434 | mypara.sip := TheRequest.RemoteAddress; 435 | if NOT isSessionValid( mypara ) then 436 | begin 437 | Render(err_page, [myPara.LastError]); 438 | exit; 439 | end; 440 | 441 | case myPara.sCmd of 442 | 'chgtpc' : Tpc_Save ( myPara ); // change a topic 443 | 'chngpst' : Pst_Save ( myPara ); // show posting in bbs_editpst.html 444 | 'deltpst' : PstDelete( myPara ); // delete a posting 445 | else 446 | begin 447 | Render(err_page, ['Funktion fehlt oder unbekannt: ' + myPara.sCmd ]); 448 | exit; 449 | end; 450 | end; 451 | 452 | 453 | end; 454 | 455 | initialization 456 | TChange.Register('change'); 457 | 458 | end. 459 | 460 | -------------------------------------------------------------------------------- /dependencies.txt: -------------------------------------------------------------------------------- 1 | EasyBBS Fast-CGI Sample Requirements: 2 | 3 | Compile : 4 | Lazarus : > 1.2.0 5 | Synapse : 4.0 6 | Brook Framework : > 3.0 7 | 8 | Run 9 | DB & Designs : https://www.bergertime.eu/download/BBS_setup_de.zip -------------------------------------------------------------------------------- /fevent.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 07.03.14 5 | // handle footer events 6 | // redirect to call page 7 | // sample href="/cgi-bin/bbs/event?ev=3&sesn=xxx 8 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 9 | 10 | unit fevent; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses 17 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 18 | FmtBCD, sqldb, blowcryp, mapping, menu; 19 | 20 | type 21 | Tfevent = class(TBrookAction) 22 | public 23 | procedure Get; override; 24 | end; 25 | 26 | implementation 27 | 28 | procedure Tfevent.Get; 29 | Var 30 | i : integer; 31 | sRedirect : String; 32 | sesnRec: sessInfType; 33 | myPara : ParaType; 34 | 35 | 36 | begin 37 | // build redirect string & read paras 38 | for I := 0 to Pred(Params.Count) do 39 | begin 40 | if sRedirect <> '' then sRedirect += '&'; 41 | sRedirect += Params.Names[i] + '=' + Params.Values[Params.Names[i]]; // Params.Items[I].AsString; 42 | case Params.Names[i] of 43 | 'ev' : myPara.sPst := Params.Values['ev']; 44 | 'sesn' : myPara.VSession := Params.Values['sesn']; 45 | end 46 | end; 47 | 48 | mypara.sip:= TheRequest.RemoteAddress; 49 | if NOT isSessionValid( mypara ) then 50 | begin 51 | Render(err_page, [myPara.LastError]); 52 | exit; 53 | end; 54 | 55 | // read session info 56 | sesnRec.id := myPara.VSession; 57 | sesn_Read( BrookFCLFCGIBroker.conn, sesnRec); 58 | 59 | case myPara.sPst of 60 | '1' : sesnRec.v_order := '1'; // sort order 61 | '2' : sesnRec.v_order := '2'; 62 | '3' : sesnRec.v_order := '3'; 63 | '4' : if sesnRec.v_page <> '0' then sesnRec.v_page := sMinus( sesnRec.v_page ); // prev page 64 | '5' : if sesnRec.v_eof = '0' then sesnRec.v_page := sPlus ( sesnRec.v_page ); // next page 65 | end; 66 | 67 | myPara.LastError := sesn_update ( BrookFCLFCGIBroker.conn, sesnRec); 68 | if myPara.LastError <> '' then 69 | begin 70 | Render(err_page, [myPara.LastError]); 71 | exit; 72 | end; 73 | 74 | // return to caller 75 | redirect (sesnRec.forwarded_for + '&sesn=' + myPara.VSession, 302); 76 | 77 | end; 78 | 79 | initialization 80 | Tfevent.Register('event'); 81 | 82 | end. 83 | 84 | -------------------------------------------------------------------------------- /find.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 19.03.14 5 | // file : find.pas 6 | // search posts & topics 7 | // for user, headline, date or publish fulltext 8 | 9 | unit find; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses 16 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 17 | FmtBCD, mysql55conn, sqldb, blowcryp, mapping, menu; 18 | 19 | 20 | type 21 | Tfind = class(TBrookAction) 22 | public 23 | procedure Get; override; 24 | procedure Post; override; 25 | end; 26 | 27 | implementation 28 | 29 | ////////////////////////////////////////////////////////// 30 | // validate bbs_find.html form entries 31 | // show error page on: all empty, 32 | // certain paras leading to empty result 33 | // otherwise : redirect to ./findrslt 34 | 35 | procedure Tfind.Post; 36 | var 37 | I : integer; 38 | mySessn: sessInfType; 39 | myPara : paraType; 40 | memFrm : ForInfType; 41 | memTpc : TopInfType; 42 | PstFrm : PstInfType; 43 | usrFrm1: usrInfType; 44 | query : TSQLQuery; 45 | sRslt, body, sDate : String; 46 | 47 | begin 48 | 49 | // read para 50 | for I := 0 to Fields.Count-1 do 51 | begin 52 | case Fields.Names[i] of 53 | 'sesn' : myPara.VSession := Fields.Values[Fields.Names[i]]; 54 | 'Tpc' : myPara.sTopic := Fields.Values[Fields.Names[i]]; 55 | 'user' : myPara.sID := Fields.Values[Fields.Names[i]]; 56 | 'date' : myPara.sPst := Fields.Values[Fields.Names[i]]; 57 | 'S1' : myPara.text2 := Fields.Values[Fields.Names[i]]; 58 | 'B2' : myPara.sCmd := Fields.Values[Fields.Names[i]]; 59 | 'B3' : myPara.sCmd := Fields.Values[Fields.Names[i]]; 60 | end; 61 | end; 62 | 63 | // cancel on quit 64 | if myPara.sCmd = 'quit' then 65 | begin 66 | redirect ('main?sesn=' + myPara.VSession, 302); 67 | exit 68 | end; 69 | 70 | // cancel on unknown command 71 | if myPara.sCmd <> 'find' then 72 | begin 73 | Render(err_page, ['unknow command: ' + myPara.sCmd]); 74 | exit 75 | end; 76 | 77 | // exit on invalid session 78 | mypara.sip:= TheRequest.RemoteAddress; 79 | if NOT isSessionValid( mypara ) then 80 | begin 81 | Render(err_page, [myPara.lastError]); 82 | exit; 83 | end; 84 | 85 | // read session rec 86 | mySessn.id := mypara.VSession; 87 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 88 | sesn_copy_para( mySessn, myPara ); 89 | 90 | // avoid code injection 91 | myPara.sTopic := SecuredStr(myPara.sTopic); // headline 92 | myPara.sID := SecuredStr(myPara.sID); // author 93 | myPara.sPst := SecuredStr(myPara.sPst); // publish date 94 | myPara.text2 := SecuredStr(myPara.text2); // medium blob text 95 | 96 | 97 | // exit on all empty 98 | if (myPara.sTopic = '') AND 99 | (myPara.sID = '' ) AND 100 | (myPara.sPst = '' ) AND 101 | (myPara.text2 = '' ) then 102 | begin 103 | Render(err_page, ['Keine Suchangaben ..']); 104 | exit; 105 | end; 106 | 107 | query := TSQLQuery.Create(nil); 108 | query.DataBase := BrookFCLFCGIBroker.conn; 109 | 110 | ///////////////////////////////// 111 | // entry fields check queries 112 | sRslt := ''; 113 | myPara.lastError := ''; 114 | 115 | // search author 116 | if myPara.sID <> '' then 117 | begin 118 | // find user(s) 119 | sRslt := 'WHERE Name like "%' + myPara.sID + '%" '; 120 | query.SQL.Text := 'select * from user where name like "%' + myPara.sID +'%"' ; 121 | query.Open; 122 | if query.eof then myPara.lastError += 'Keine Author(en) gefunden: ' + myPara.sID + '

'; 123 | query.active := False; 124 | end; 125 | 126 | // search Headline in posts and topics - valid on any result 127 | if myPara.sTopic <> '' then 128 | begin 129 | sRslt += iif(sRslt='','WHERE ',' AND ') + '( post_subject like "%' + myPara.sTopic + '%" OR title like "%' + myPara.sTopic + '%" ) '; 130 | query.SQL.Text := 'SELECT * FROM posts where post_subject like "%' + myPara.sTopic + '%";'; 131 | query.Open; 132 | if query.eof then 133 | begin 134 | query.active := False; 135 | query.SQL.Text := 'SELECT * FROM topics where title like "' + myPara.sTopic + '%";'; 136 | query.Open; 137 | if query.eof then myPara.lastError += 'Kein Thema oder Nachricht mit Überschrift: ' + myPara.sTopic + '

'; 138 | end; 139 | query.active := False; 140 | end; 141 | 142 | // search Date in posts and topics - valid on any result 143 | if myPara.sPst <> '' then 144 | begin 145 | sDate := FormatDateTime('yyyy-mm-dd', StrToDate(myPara.sPst)); 146 | sRslt += iif(sRslt='','WHERE ',' AND ') + 'post_time like "' + sDate +'%" ' ; 147 | query.SQL.Text := 'SELECT * FROM posts where post_time like "' + sDate + '%" OR post_edit_time like "' + sDate + '%";'; 148 | query.Open; 149 | if query.eof then 150 | begin 151 | query.active := False; 152 | query.SQL.Text := 'SELECT * FROM topics where ctime like "' + sDate + '%" OR last_post_time like "' + sDate + '%";'; 153 | query.Open; 154 | if query.eof then myPara.lastError += 'Keine Themen oder Nachrichten am: ' + sDate + '

'; 155 | end; 156 | query.active := False; 157 | end; 158 | 159 | // search text in blob 160 | if myPara.text2 <> '' then 161 | begin 162 | myPara.text2 := StripHTML( myPara.text2 ); 163 | sRslt += iif(sRslt='','WHERE ',' AND ') + 'match(post_text) AGAINST ("' + myPara.text2 + '" IN NATURAL LANGUAGE MODE) '; 164 | query.SQL.Text := 'select * from posts where match ( post_text ) AGAINST (''' + myPara.text2 + ''' IN NATURAL LANGUAGE MODE);'; 165 | query.Open; 166 | if query.eof then myPara.lastError += 'Keine Nachricht mit Inhalt: ' + myPara.text2 ; 167 | query.active := False; 168 | end; 169 | 170 | sRslt := 'SELECT * from find ' + sRslt; 171 | 172 | // exit if one search para leads to empty result 173 | if myPara.lastError <> '' then 174 | begin 175 | query.Free; 176 | Render(err_page, [myPara.lastError]); 177 | exit; 178 | end; 179 | 180 | 181 | ////////////////////// 182 | // main query 183 | query.SQL.Text := sRslt; 184 | query.Open; 185 | 186 | // exit if combined paras leads to empty result 187 | if query.eof then 188 | begin 189 | sRslt := sUpdate( findinfo,'%%5', myPara.sTopic + '.
'); 190 | sRslt := sUpdate( sRslt, '%%6', myPara.sID + '.
'); 191 | sRslt := sUpdate( sRslt, '%%7', myPara.sPst + '.
'); 192 | sRslt := sUpdate( sRslt, '%%8', myPara.text2 + '.
'); 193 | Render(err_page, ['Keine Ergebnisse für
' + sRslt]); 194 | query.active := False; 195 | query.Free; 196 | exit; 197 | end; 198 | 199 | // update session rec with blob search 200 | mySessn.lastsearch:= myPara.text2 ; 201 | sesn_update( BrookFCLFCGIBroker.conn, mySessn ); 202 | 203 | // open find result 204 | redirect ('frslt?ID=' + myPara.sID + '&Tpc=' + myPara.sTopic + 205 | '&Pst=' + myPara.sPst + '&sesn=' + myPara.VSession, 206 | 302); 207 | 208 | // release mem 209 | query.active := False; 210 | query.Free; 211 | 212 | 213 | end; 214 | 215 | ////////////////////////////////////////////////////////// 216 | // render bbs_find.html form 217 | // add session info to header & footer 218 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 219 | 220 | procedure Tfind.Get; 221 | var 222 | I : integer; 223 | sMenu : String; 224 | mySessn: sessInfType; 225 | myPara : paraType; 226 | 227 | 228 | begin 229 | // check session 230 | mypara.VSession := Params.Values['sesn']; 231 | mypara.sip:= TheRequest.RemoteAddress; 232 | if NOT isSessionValid( mypara ) then 233 | begin 234 | Render(err_page, [myPara.lastError]); 235 | exit; 236 | end; 237 | 238 | // callback target 239 | paraTypeInit('find?', myPara ); // init mypara 240 | mypara.sCmd := '1'; // '1' full header menu 241 | mySessn.id := mypara.VSession; 242 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 243 | sesn_copy_para( mySessn, myPara ); 244 | 245 | sMenu := make_header(mypara); 246 | mypara.sCmd := '0'; // no nav or search in footer 247 | 248 | // display 249 | Render('bbs_find.html', [ sMenu, 250 | mypara.VSession, 251 | make_footer( BrookFCLFCGIBroker.conn, mypara)]); 252 | 253 | 254 | end; 255 | 256 | initialization 257 | Tfind.Register('find'); 258 | 259 | end. 260 | 261 | -------------------------------------------------------------------------------- /forums.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 11.02.14 5 | // file : forums.pas 6 | // modified : 12.03.14 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | // called via: 'cgi1/forum?ID=XXXX&sesn=XXXXXXXXXXXXXXX' 9 | 10 | unit forums; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses 17 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 18 | FmtBCD, sqldb, mapping, blowcryp, menu; 19 | 20 | type 21 | TForum = class(TBrookAction) 22 | public 23 | procedure Get; override; 24 | end; 25 | 26 | 27 | implementation 28 | 29 | 30 | procedure TForum.Get; 31 | var 32 | i : integer; 33 | sBody, sLink, sInfo, sTmp : string; 34 | memFrm : ForInfType; 35 | memTpc : TopInfType; 36 | mypara : ParaType; 37 | mySessn: sessInfType; 38 | query : TSQLQuery; 39 | 40 | 41 | 42 | begin 43 | // check paras 44 | memTpc.forum_id := Params.Values['ID']; 45 | mypara.VSession := Params.Values['sesn']; 46 | if memTpc.forum_id = '' then 47 | begin 48 | Render(err_page, ['Forum ID fehlt.' ]); 49 | exit; 50 | end; 51 | mypara.sip:= TheRequest.RemoteAddress; 52 | if NOT isSessionValid( mypara ) then 53 | begin 54 | Render(err_page, [mypara.lastError]); 55 | exit; 56 | end; 57 | 58 | // read session record 59 | paraTypeInit('forum?', myPara ); // preset myPara 60 | mySessn.id := mypara.VSession; 61 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 62 | sesn_copy_para( mySessn, myPara ); 63 | 64 | // set display order 65 | case myPara.v_order of 66 | '0' : sTmp := '' ; 67 | '1' : sTmp := ' ORDER BY last_post_time'; 68 | '2' : sTmp := ' ORDER BY views'; 69 | '3' : sTmp := ' ORDER BY title'; 70 | end; 71 | 72 | // read forum info 73 | ReadForum( BrookFCLFCGIBroker.conn, 'where id=' + memTpc.forum_id, memFrm ); 74 | 75 | // query 76 | query := TSQLQuery.Create(nil); 77 | query.DataBase := BrookFCLFCGIBroker.conn; 78 | query.SQL.Text := 'SELECT * FROM topics where forum_id=' + 79 | memTpc.forum_id + // parent forum 80 | sTmp + // order by 81 | ' limit ' + // limit start,stop 82 | IntToStr( StrToInt( myPara.v_page ) * PageItems ) 83 | + ',' + IntToStr( StrToInt( myPara.v_page ) * PageItems + PageItems+1 ); 84 | query.Open; 85 | 86 | // loop through records til limit 87 | // we set limit+1 to use query.eof for navibar handler 88 | i := 0; 89 | while not query.EOF do 90 | begin 91 | sTmp := '' + 92 | '
%%0
%%1
' + #13; 93 | 94 | // sLink sample : erstes Topic 95 | // &page=0 used in /topic to reset session.vpage 96 | sLink := ' ' + 99 | query.FieldByName('title').asString + '
' + 100 | LEFTSTR ( query.FieldByName('topic_text').asString, 120) + ' .. ' ; 101 | sTmp := sUpdate ( sTmp, '%%0', sLink ); // para %%0 : title 102 | 103 | // sInfo sample : von: Kleeblatt am: 30.12.2013 Hits: 0 Posts: 0 104 | sInfo := ' erstellt von: ' + query.FieldByName('poster_name').asString + 105 | ' am: ' + query.FieldByName('ctime').asString + 106 | ' Zugriffe: ' + query.FieldByName('views').asString + 107 | ' Antworten: ' + query.FieldByName('replies').asString; 108 | sTmp := sUpdate ( sTmp, '%%1', sInfo ); // para %%1 : info 109 | sBody += sTmp; 110 | i += 1; 111 | if i = PageItems then break; 112 | query.next; 113 | end; 114 | 115 | // build mypara for header & footer menus 116 | mypara.sCmd := '1'; // '1' full record 117 | myPara.v_eof := iif( query.EOF, '1', '0'); // eof flag 118 | mypara.V_rec := query.FieldByName('id').asString; // last recid 119 | mypara.Text1 := 'forum?ID=' + memTpc.forum_id; // saved in session.forward_for 120 | mypara.sID := memTpc.forum_id ; // Header Menu Para 121 | mypara.sTopic:= memFrm.fName ; // Header Menu Text 122 | 123 | // display 124 | Render('bbs_topic.html', [make_Header_newThm(mypara), 125 | sBody, 126 | make_Footer( BrookFCLFCGIBroker.conn, mypara )]) ; 127 | 128 | // release db 129 | query.active := false; 130 | query.free; 131 | 132 | end; 133 | 134 | 135 | 136 | initialization 137 | TForum.Register('forum'); 138 | end. 139 | 140 | -------------------------------------------------------------------------------- /frslt.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 20.03.14 5 | // file : frslt.pas 6 | // list posts & topics results from find.pas as table 7 | // use template bbs_findrslt.html 8 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 9 | 10 | unit frslt; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses 17 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 18 | FmtBCD, sqldb, blowcryp, mapping, menu; 19 | 20 | 21 | type 22 | Tfrslt = class(TBrookAction) 23 | public 24 | procedure Get; override; 25 | end; 26 | 27 | implementation 28 | 29 | procedure Tfrslt.Get; 30 | var 31 | i : integer; 32 | sRslt, body, sDate : String; 33 | mySessn: sessInfType; 34 | myPara : paraType; 35 | query : TSQLQuery; 36 | 37 | begin 38 | 39 | // read paras 40 | myPara.VSession := Params.Values['sesn']; 41 | myPara.sID := Params.Values['ID']; 42 | myPara.sTopic := Params.Values['Tpc']; 43 | myPara.sPst := Params.Values['Pst']; 44 | // check session timeout 45 | mypara.sip:= TheRequest.RemoteAddress; 46 | if NOT isSessionValid( mypara ) then 47 | begin 48 | Render(err_page, ['session timeout ' + myPara.lastError + myPara.VSession + inttostr(i) ]); 49 | exit; 50 | end; 51 | 52 | 53 | // get session info 54 | paraTypeInit('frslt?', myPara ); // init mypara 55 | mypara.sCmd := '1'; // '1' full menus 56 | mySessn.id := mypara.VSession; // read session rec 57 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 58 | sesn_copy_para( mySessn, myPara ); 59 | myPara.text1 := 'frslt?ID=' + myPara.sID + // add search paras 60 | '&Tpc=' + myPara.sTopic + 61 | '&Pst=' + myPara.sPst + 62 | '&sesn=' + myPara.VSession; 63 | myPara.text2 := mySessn.lastsearch; // blob search from session rec 64 | 65 | 66 | // build query 67 | if myPara.sID <>'' then sRslt += 'WHERE Name like "%' + myPara.sID + '%" '; 68 | if myPara.sTopic<>'' then sRslt += iif(sRslt='','WHERE ',' AND ') + '( post_subject like "%' + myPara.sTopic + '%" OR title like "%' + myPara.sTopic + '%" ) '; 69 | if myPara.sPst <>'' then sRslt += iif(sRslt='','WHERE ',' AND ') + 'post_time like "' + FormatDateTime('yyyy-mm-dd', StrToDate(myPara.sPst)) +'%" ' ; 70 | if myPara.text2 <>'' then sRslt += iif(sRslt='','WHERE ',' AND ') + 'match(post_text) AGAINST ("' + myPara.text2 + '" IN NATURAL LANGUAGE MODE) '; 71 | sRslt := 'SELECT * from find ' + sRslt; 72 | 73 | // set display order 74 | case myPara.v_order of 75 | '1' : sRslt += ' ORDER BY post_time'; 76 | '2' : sRslt += ' ORDER BY iduser'; 77 | '3' : sRslt += ' ORDER BY forum_id'; 78 | end; 79 | 80 | // set limit ( start,stop ) 81 | sRslt += ' limit ' + 82 | IntToStr( StrToInt( myPara.v_page ) * PageItems ) + ',' + 83 | IntToStr( StrToInt( myPara.v_page ) * PageItems + PageItems+1 ); 84 | 85 | ////////////////////// 86 | // main query 87 | query := TSQLQuery.Create(nil); 88 | query.DataBase := BrookFCLFCGIBroker.conn; 89 | query.SQL.Text := sRslt; 90 | query.Open; 91 | 92 | i := 0; 93 | body := ''; 94 | while not query.EOF do 95 | begin 96 | sRslt := sUpdate(findrslt,'%%1','' + 98 | query.FieldByName('fname').AsString + '' ); 99 | sRslt := sUpdate( sRslt, '%%2','' + 102 | query.FieldByName('title').AsString + '' ); 103 | sRslt := sUpdate( sRslt, '%%3',StripHTML( query.FieldByName('post_text').AsString) ); 104 | sRslt := sUpdate( sRslt, '%%4','' + 106 | query.FieldByName('Name').AsString + '' ); 107 | body += sRslt; 108 | i += 1; 109 | if i = PageItems then break; 110 | query.next; 111 | end; 112 | 113 | // Build last table line 114 | // display blanks as .. 115 | sRslt := sUpdate( findinfo, '%%5', iif( myPara.sTopic='', '..', myPara.sTopic)); 116 | sRslt := sUpdate( sRslt, '%%6', iif( myPara.sID ='', '..', myPara.sID)); 117 | sRslt := sUpdate( sRslt, '%%7', iif( myPara.sPst ='', '..', myPara.sPst)); 118 | sRslt := sUpdate( sRslt, '%%8', iif( myPara.text2 ='', '..', myPara.text2)); 119 | body += sRslt; 120 | 121 | // set footer info 122 | myPara.v_eof := iif( query.EOF, '1', '0'); // eof flag 123 | 124 | // show page 125 | Render('bbs_findrslt.html', [ make_header(mypara), // header 126 | body, // body 127 | make_footer( BrookFCLFCGIBroker.conn, mypara) ]); // footer 128 | // release mem 129 | query.active := False; 130 | query.Free; 131 | 132 | end; 133 | 134 | initialization 135 | Tfrslt.Register('frslt'); 136 | 137 | end. 138 | 139 | -------------------------------------------------------------------------------- /geoinfo.pas: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // file : geoinfo.pas 4 | // created : 07.05.14 5 | // function : show active bbs users on google maps 6 | // called via: bbs/geoinfo 7 | // paras : s1 = latlon positions, s2 = marker, s3 = boundary elements 8 | // s4 = header, s5 = footer 9 | 10 | unit geoinfo; 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses 16 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 17 | FmtBCD, sqldb, blowcryp, mapping, menu; 18 | 19 | CONST 20 | 21 | sPos = 'var <> = new google.maps.LatLng(<>, <>);' + #13; 22 | sMark = 'var <> = new google.maps.Marker({ position: <>, map: map, title: ''<>'' });' + #13; 23 | sBound = 'Bounds.extend(<>);' + #13 ; 24 | 25 | 26 | type 27 | Tgeoinfo = class(TBrookAction) 28 | public 29 | procedure Get; override; 30 | end; 31 | 32 | implementation 33 | 34 | procedure Tgeoinfo.Get; 35 | var 36 | i : integer; 37 | poscalc : extended; 38 | 39 | myPos, myMark, myBound, 40 | tPos, tMark, tBound, 41 | myLat, myLon : String; 42 | 43 | mypara : paraType; 44 | usrFrm1: usrInfType; 45 | mySessn: sessInfType; 46 | query : TSQLQuery; 47 | 48 | begin 49 | 50 | // check session 51 | mypara.VSession := Params.Values['sesn']; 52 | mypara.sip:= TheRequest.RemoteAddress; 53 | if NOT isSessionValid( mypara ) then 54 | begin 55 | Render(err_page, [myPara.lastError]); 56 | exit; 57 | end; 58 | 59 | // preset myPara 60 | paraTypeInit('geoinfo?', myPara ); // callback target for footer 61 | mypara.sCmd := '1'; // '1' full menus 62 | mySessn.id := mypara.VSession; 63 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 64 | sesn_copy_para( mySessn, myPara ); 65 | 66 | // query 67 | query := TSQLQuery.Create(nil); 68 | query.DataBase := BrookFCLFCGIBroker.conn; 69 | query.SQL.Text := 'select * from sessions where is_active = 1;'; 70 | query.Open; 71 | 72 | if query.EOF then 73 | begin 74 | query.active := false; 75 | query.free; 76 | Render(err_page, ['No Users online.']); 77 | exit; 78 | end; 79 | 80 | // loop throug open sessions 81 | i := 1; 82 | while not query.EOF do 83 | begin 84 | cpySessInfo ( query, mySessn ); 85 | // read session user 86 | ReadUsr( conn, 'where iduser=' + mySessn.user_id , usrFrm1 ); 87 | 88 | // get best lat/lon 89 | /// lat 90 | if (Length(mySessn.longitude) > Length(mySessn.sLong)) then 91 | poscalc := StrToFloat(mySessn.longitude) 92 | else 93 | poscalc := StrToFloat(mySessn.sLong); 94 | poscalc := poscalc + i * 0.000007; // avoid stacks on map 95 | myLon := FloatToStr( poscalc ); 96 | /// lat 97 | if (Length(mySessn.latitude) > Length(mySessn.sLat)) then 98 | poscalc := StrToFloat(mySessn.latitude) 99 | else 100 | poscalc := StrToFloat(mySessn.sLat); 101 | poscalc := poscalc + i * 0.000007; // avoid stacks on map 102 | myLat := FloatToStr( poscalc ); 103 | 104 | // build java script inserts 105 | myPos := sUpdate( sPos, '<>', 'pos' + IntToStr(i) ); // set var name 106 | myPos := sUpdate( myPos, '<>', sUpdate(myLat, ',','.')); // set vars lat 107 | myPos := sUpdate( myPos, '<>', sUpdate(myLon, ',', '.')); // set vars lon 108 | tPos += myPos; 109 | 110 | myMark := sUpdate( sMark, '<>', 'mark' + IntToStr(i) ); // set marker name 111 | myMark := sUpdate( myMark, '<>', 'pos' + IntToStr(i) ); // set var name 112 | myMark := sUpdate( myMark, '<>', usrFrm1.Name ); // set marker info 113 | tMark += myMark; 114 | 115 | myBound:= sUpdate( sBound, '<>', 'pos' + IntToStr(i) ); // set boundary 116 | tBound += myBound; 117 | i += 1; 118 | query.Next; 119 | end; 120 | 121 | 122 | // display geo_pos 123 | Render('bbs_geopos.html', [tPos, tMark, tBound, 124 | make_Header( mypara ), 125 | make_Footer( BrookFCLFCGIBroker.conn, mypara ) ]); 126 | 127 | // release mem 128 | query.active := false; 129 | query.free; 130 | 131 | 132 | end; 133 | 134 | 135 | initialization 136 | Tgeoinfo.Register('geoinfo'); 137 | 138 | end. 139 | 140 | -------------------------------------------------------------------------------- /info.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 01.03.14 5 | // list active users 6 | // show info tiles ( total , logins, href to user posts( upst ) 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | 9 | unit info; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses 16 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 17 | FmtBCD, strutils, sqldb, blowcryp, mapping, menu; 18 | 19 | type 20 | TInfo = class(TBrookAction) 21 | public 22 | procedure Get; override; 23 | end; 24 | 25 | implementation 26 | 27 | procedure TInfo.Get; 28 | var 29 | I : Integer; 30 | sTiles, kachel, sTmp : string; 31 | usrFrm1: usrInfType; 32 | mySessn: sessInfType; 33 | myPara : paraType; 34 | query : TSQLQuery; 35 | 36 | 37 | begin 38 | // check session 39 | mypara.VSession := Params.Values['sesn']; 40 | mypara.sip:= TheRequest.RemoteAddress; 41 | if NOT isSessionValid( mypara ) then 42 | begin 43 | Render(err_page, [myPara.lastError]); 44 | exit; 45 | end; 46 | 47 | 48 | // callback target 49 | paraTypeInit('info?', myPara ); // init mypara 50 | mypara.sCmd := '1'; // '1' full menus 51 | mySessn.id := mypara.VSession; 52 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 53 | sesn_copy_para( mySessn, myPara ); 54 | 55 | // set display order 56 | case myPara.v_order of 57 | '0' : sTmp := '' ; 58 | '1' : sTmp := ' ORDER BY login'; 59 | '2' : sTmp := ' ORDER BY latitude, longitude'; 60 | '3' : sTmp := ' ORDER BY user_id'; 61 | end; 62 | 63 | 64 | // query 65 | query := TSQLQuery.Create(nil); 66 | query.DataBase := BrookFCLFCGIBroker.conn; 67 | query.SQL.Text := 'select * from sessions where is_active = 1' + 68 | sTmp + // order by 69 | ' limit ' + // limit start,stop 70 | IntToStr( StrToInt( myPara.v_page ) * PageItems ) 71 | + ',' + IntToStr( StrToInt( myPara.v_page ) * PageItems + PageItems+1 ); 72 | query.Open; 73 | 74 | if query.EOF then 75 | begin 76 | query.active := false; 77 | query.free; 78 | Render(err_page, ['No Users online.']); 79 | exit; 80 | end; 81 | 82 | // loop throug open sessions 83 | i := 0; 84 | sTiles := ''; 85 | while not query.EOF do 86 | begin 87 | cpySessInfo ( query, mySessn ); 88 | // read session user 89 | ReadUsr( conn, 'where iduser=' + mySessn.user_id , usrFrm1 ); 90 | // set user tile 91 | kachel := sUpdate( usrTile,'%%0', mySessn.user_id ); // UserID 92 | kachel := sUpdate( kachel, '%%1', iif((i mod 2=1),'rkachel','bkachel')); // tile(red/blue) 93 | kachel := sUpdate( kachel, '%%2', usrFrm1.Name ); // UserName 94 | kachel := sUpdate( kachel, '%%3', showUsrImage(usrFrm1)); // User PNG 95 | kachel := sUpdate( kachel, '%%4', MIDSTR(mySessn.login,12,5)); // Session start ( HH:MM ) 96 | kachel := sUpdate( kachel, '%%5', usrFrm1.TotalTime ); // User logins 97 | kachel := sUpdate( kachel, '%%6', myPara.VSession ); // Session ID 98 | sTiles += kachel; 99 | i += 1; 100 | if i = PageItems then break; 101 | query.Next; 102 | end; 103 | 104 | // prepare & render 105 | // Update Session info 106 | myPara.v_rec := mySessn.rid; // last rec in display 107 | myPara.v_eof := iif( query.EOF, '1', '0'); // eof flag 108 | 109 | Render('bbs_onln.html', [ make_header(mypara), 110 | sTiles, 111 | make_footer( BrookFCLFCGIBroker.conn, mypara)]); 112 | 113 | // release mem 114 | query.active := false; 115 | query.free; 116 | 117 | end; 118 | 119 | initialization 120 | TInfo.Register('info'); 121 | 122 | end. 123 | 124 | -------------------------------------------------------------------------------- /legal.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 02.03.14 5 | // render forms : bbs_terms.html, bbs_imprint.html, bbs_privacy.html 6 | // select via : legal?actn=1,2,3 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | 9 | unit legal; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses 16 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 17 | FmtBCD, sqldb, blowcryp, mapping, menu; 18 | 19 | type 20 | TLegal = class(TBrookAction) 21 | public 22 | procedure Get; override; 23 | end; 24 | 25 | implementation 26 | 27 | procedure TLegal.Get; 28 | var 29 | 30 | bSessn : boolean; 31 | sActn : String; 32 | myPara : ParaType; 33 | mySessn : sessInfType; 34 | sMenu, sFooter : string; 35 | 36 | 37 | begin 38 | 39 | sActn := Params.Values['actn']; 40 | mypara.VSession := Params.Values['sesn']; 41 | if sActn = '' then 42 | begin 43 | Render(err_page, ['Action ID fehlt.']); 44 | exit; 45 | end; 46 | 47 | // no break on expired session - always render legal forms 48 | mypara.sip:= TheRequest.RemoteAddress; 49 | bSessn:= isSessionValid( mypara ) ; 50 | 51 | // preset myPara 52 | paraTypeInit('legal?actn=' + sActn, myPara ); 53 | 54 | // read session record 55 | if bSessn then 56 | begin 57 | mySessn.id := mypara.VSession; 58 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 59 | sesn_copy_para( mySessn, myPara ); 60 | end; 61 | 62 | mypara.sCmd := iif ( bSessn, '1', '0'); 63 | 64 | sMenu := make_Header( mypara ); 65 | sFooter := make_Footer( BrookFCLFCGIBroker.conn, mypara ); 66 | if mypara.lastError <> '' then 67 | begin 68 | Render(err_page, [mypara.lastError]); 69 | exit; 70 | end; 71 | 72 | // render template 73 | case sActn of 74 | '1' : Render('bbs_terms.html', [ sMenu, GetContent( BrookFCLFCGIBroker.conn, 'AGB'), sFooter ]); 75 | '2' : Render('bbs_terms.html', [ sMenu, GetContent( BrookFCLFCGIBroker.conn, 'Privacy'), sFooter ]); 76 | '3' : Render('bbs_terms.html', [ sMenu, GetContent( BrookFCLFCGIBroker.conn, 'Imprint'), sFooter ]); 77 | else 78 | Render(err_page, ['Action ID unbekannt:' + sActn +'.']); 79 | end; 80 | 81 | end; 82 | 83 | initialization 84 | TLegal.Register('legal'); 85 | 86 | end. 87 | 88 | 89 | -------------------------------------------------------------------------------- /logout.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 01.03.14 5 | // file : Logout.pas 6 | // close session record 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | 9 | unit Logout; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses 16 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 17 | FmtBCD, sqldb, blowcryp, mapping, menu; 18 | 19 | type 20 | TGoodBye = class(TBrookAction) 21 | public 22 | procedure Get; override; 23 | end; 24 | 25 | implementation 26 | 27 | procedure TGoodBye.Get; 28 | var 29 | SessRec: sessInfType; 30 | myPara : ParaType; 31 | 32 | begin 33 | // check session 34 | myPara.VSession := Params.Values['sesn']; 35 | mypara.sip:= TheRequest.RemoteAddress; 36 | if NOT isSessionValid( mypara ) then 37 | begin 38 | redirect ('./main?',302); 39 | exit; 40 | end; 41 | 42 | // close session 43 | SessRec.user_id := IntToStr( myPara.userID ); 44 | sesn_close( BrookFCLFCGIBroker.conn, SessRec ); 45 | 46 | // free mem 47 | redirect ('./main?',302); 48 | 49 | end; 50 | 51 | initialization 52 | TGoodBye.Register('quit'); 53 | 54 | end. 55 | 56 | -------------------------------------------------------------------------------- /main.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 08.05.14 5 | // file : main.pas 6 | // called via: cgi1/main?sesn=xx 7 | // or: cgi1/main for login dialog 8 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 9 | // : 27.04.14 - change para read 10 | 11 | unit main; 12 | 13 | {$mode objfpc}{$H+} 14 | 15 | interface 16 | 17 | uses 18 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 19 | FmtBCD, sqldb, blowcryp, mapping, menu; 20 | 21 | type 22 | TWelcome = class(TBrookAction) 23 | public 24 | procedure Get; override; 25 | procedure Post; override; 26 | end; 27 | 28 | 29 | implementation 30 | 31 | procedure TWelcome.Post; 32 | var 33 | VUser, VPass, VCmd, sTmp : string; 34 | usrRec : usrInfType; 35 | sesnRec : sessInfType; 36 | 37 | 38 | begin 39 | 40 | // post w/o paras? -> only refresh main page ( not logged in ) 41 | if Fields.Count = 0 then 42 | begin 43 | redirect ('./main?',302); 44 | exit; 45 | end; 46 | 47 | // copy paras 48 | VUser := SecuredStr(Fields.Values['usr'] ); 49 | VPass := SecuredStr(Fields.Values['pwd'] ); 50 | VCmd := SecuredStr(Fields.Values['btn'] ); 51 | sesnRec.latitude := Fields.Values['lat']; 52 | sesnRec.longitude := Fields.Values['lon']; 53 | sesnRec.accuracy := Fields.Values['acc']; 54 | 55 | 56 | // check paras 57 | if (VCmd = 'Anmelden') then 58 | begin 59 | if ( VUser = '' ) OR ( VPass = '' ) then 60 | begin 61 | Render(err_page, ['Username oder Passwort dürfen nicht leer sein.']); 62 | exit; 63 | end; 64 | end; 65 | 66 | if (VCmd = 'Abbrechen') then 67 | begin 68 | redirect ('./main?',302); 69 | exit; 70 | end; 71 | 72 | if (VCmd = 'neues Konto') then 73 | begin 74 | redirect ('./accnt?',302); 75 | exit; 76 | end; 77 | 78 | 79 | ReadUsr( BrookFCLFCGIBroker.conn, 'where name = "' + VUser +'"', usrRec ); 80 | if usrRec.name = '' then 81 | begin 82 | Render(err_page, ['Username unbekannt']); 83 | exit; 84 | end; 85 | 86 | // check pwd 87 | if usrRec.pwd <> TRIM( VPass ) then 88 | begin 89 | Render(err_page, ['Falsches PWD']); 90 | exit; 91 | end; 92 | 93 | // check registration 94 | if usrRec.isChecked <> 'True' then 95 | begin 96 | Render(err_page, ['Account nicht aktiviert.']); 97 | exit; 98 | end; 99 | 100 | // update user record 101 | usrRec.picture_png := ''; // avoid blob save -> speed up 102 | usrRec.TotalTime := sPlus(usrRec.TotalTime); // incr login count 103 | sesnRec.lastlogin := usrRec.LastTime; // rescue old LastLogin 104 | usrRec.LastTime := DateTimeToStr( now ); // set login time 105 | sTmp := updUser( BrookFCLFCGIBroker.conn, usrRec ); 106 | if sTmp <> '' then 107 | begin 108 | Render(err_page, [ sTmp ]); 109 | exit; 110 | end; 111 | 112 | // add session record 113 | sesnRec.browser := TheRequest.UserAgent; 114 | sesnRec.sip := TheRequest.RemoteAddress; 115 | sesnRec.user_id := usrRec.iduser; // add user_id 116 | codeSessionID( sesnRec ); // create sesnRec.id 117 | sesnRec.is_active := '1'; // active = true 118 | sesnRec.last_forum := sesnRec.forum_id ; // 119 | sesnRec.forum_id := '0'; 120 | sesnRec.forwarded_for:= 'main?sesn=' + sesnRec.id; 121 | sesnRec.v_page := '0'; 122 | sesnRec.v_rec := '1'; 123 | sesnRec.v_order := '1'; 124 | sesnRec.v_eof := '0'; 125 | sesnRec.last_post_cnt:= posts_Count( BrookFCLFCGIBroker.conn, sesnRec.lastlogin ); 126 | GetIPLatLon( GetSetting( BrookFCLFCGIBroker.conn,'GeoIP') + sesnRec.sip, 127 | sesnRec.sLat, sesnRec.sLong ); 128 | 129 | sTmp := sesn_insert ( BrookFCLFCGIBroker.conn, sesnRec); 130 | if sTmp <> '' then 131 | begin 132 | Render(err_page, [sTmp]); 133 | exit; 134 | end; 135 | 136 | // show homepage 137 | redirect ( './main?sesn=' + sesnRec.id, 302 ); 138 | 139 | end; 140 | 141 | { TWelcome } 142 | procedure TWelcome.Get; 143 | var 144 | i : integer; 145 | sTiles, Kachel, sTmp : string; 146 | bSessn : boolean; 147 | myPara : ParaType; 148 | memQry : ForInfType; 149 | mySessn : sessInfType; 150 | query : TSQLQuery; 151 | 152 | begin 153 | 154 | // check session 155 | myPara.VSession := Params.Values['sesn']; 156 | mypara.sip:= TheRequest.RemoteAddress; 157 | bSessn:= isSessionValid( mypara ); 158 | 159 | // preset myPara 160 | paraTypeInit('main?', myPara ); 161 | // read session record 162 | if bSessn then 163 | begin 164 | mySessn.id := mypara.VSession; 165 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 166 | sesn_copy_para( mySessn, myPara ); 167 | end; 168 | 169 | // set display order 170 | case myPara.v_order of 171 | '0' : sTmp := '' ; 172 | '1' : sTmp := ' ORDER BY last_post_time'; 173 | '2' : sTmp := ' ORDER BY posts'; 174 | '3' : sTmp := ' ORDER BY fname'; 175 | end; 176 | 177 | // query 178 | query := TSQLQuery.Create(nil); 179 | query.DataBase := BrookFCLFCGIBroker.conn; 180 | query.SQL.Text := 'select * from forums' + 181 | sTmp + // order by 182 | ' limit ' + // limit start,stop 183 | IntToStr( StrToInt( myPara.v_page ) * PageItems ) 184 | + ',' + IntToStr( StrToInt( myPara.v_page ) * PageItems + PageItems+1 ); 185 | query.Open; 186 | if query.EOF then 187 | begin 188 | query.active := false; 189 | query.free; 190 | Render(err_page, ['No Forums!']); 191 | exit; 192 | end; 193 | 194 | // generate tiles 195 | i := 0; 196 | sTiles := ''; 197 | while not query.EOF do 198 | begin 199 | cpyForumInfo( Query, memQry ); 200 | kachel := iif(bSessn, 201 | sUpdate ( tpcTile, '%%6', cgiPath + 'forum?ID=%%0&sesn=' + myPara.VSession ) , 202 | sUpdate ( tpcTile, '%%6', '#" onclick="overlay()') ); // set link 203 | kachel := sUpdate( kachel, '%%0', memQry.id ); // ForumID 204 | kachel := sUpdate( kachel, '%%1', iif((i mod 2=1),'rkachel','bkachel')); // red/blue tile 205 | kachel := sUpdate( kachel, '%%2', memQry.fname ); // ForumName 206 | kachel := sUpdate( kachel, '%%3', memQry.fdesc ); // Forum Description 207 | kachel := sUpdate( kachel, '%%4', LEFTSTR(memQry.last_post_time,6) ); // Last post ( DD.MM ) 208 | kachel := sUpdate( kachel, '%%5', memQry.topics ); // topics# 209 | sTiles += kachel; 210 | i += 1; 211 | if i = PageItems then break; 212 | query.Next; 213 | end; 214 | 215 | 216 | // Update Session info 217 | myPara.v_rec := memQry.id; // last rec in display 218 | myPara.Text1 := 'main?'; // callback target for footer 219 | myPara.v_eof := iif( query.EOF, '1', '0'); // eof flag 220 | mypara.sCmd := iif( bSessn, '1', '0'); // if session full menu else pre login menu 221 | 222 | // render 223 | Render('bbs_main.html', [ make_Header( mypara ), 224 | sTiles, 225 | make_Footer( BrookFCLFCGIBroker.conn, mypara ) ]); 226 | 227 | // release mem 228 | query.active := false; 229 | query.free; 230 | 231 | end; 232 | 233 | 234 | initialization 235 | TWelcome.Register('main'); 236 | 237 | end. 238 | -------------------------------------------------------------------------------- /mapping.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : by schema mapper V. 2.1 - 28.02.14 5 | // file : mapping.pas 6 | // created : 28.02.14 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | // 04.05.2014 Update Commit for Laz. 1.2.2 9 | // 08.05.2014 blob save as hexstr 10 | // tested : yes 11 | 12 | unit Mapping; 13 | 14 | {$mode objfpc}{$H+} 15 | 16 | interface 17 | 18 | uses 19 | Classes, SysUtils, Variants, FmtBCD, mysql55conn, sqldb, blowcryp ; 20 | 21 | const 22 | sqlDate = 'yyyy-mm-dd hh:nn:ss'; 23 | 24 | 25 | type 26 | ForInfType = record // forums record 27 | id: string; 28 | fName: string; 29 | fDesc: string; 30 | fdesc_bitfield: string; 31 | fdesc_uid: string; 32 | topics_per_page: string; 33 | posts: string; 34 | topics: string; 35 | topics_real: string; 36 | last_post_id: string; 37 | last_poster_id: string; 38 | last_post_subject: string; 39 | last_post_time : string; 40 | last_poster_name: string; 41 | end; 42 | 43 | TopInfType = record // topics record 44 | id : string; 45 | forum_id : string; 46 | title : string; 47 | topic_text : string; 48 | poster : string; 49 | poster_name : string; 50 | ctime : string; 51 | time_limit : string; 52 | views : string; 53 | replies : string; 54 | replies_real : string; 55 | first_post_id : string; 56 | first_poster_name : string; 57 | last_post_id : string; 58 | last_poster_id : string; 59 | last_poster_name : string; 60 | last_post_subject : string; 61 | last_post_time : string; 62 | last_view_time : string; 63 | end; 64 | 65 | 66 | PstInfType = record // posts record 67 | id : string; 68 | topic_id : string; 69 | forum_id : string; 70 | user_id : string; 71 | poster_ip : string; 72 | post_time : string; 73 | post_subject : string; 74 | post_text: string; 75 | post_postcount: string; 76 | post_alpha : string; 77 | post_size : string; 78 | post_edit_time : string; 79 | post_edit_reason: string; 80 | post_edit_user : string; 81 | post_edit_count : string; 82 | post_edit_locked : string; 83 | end; 84 | 85 | usrInfType = record // user record 86 | iduser : string; 87 | Name : string; 88 | pwd : string; 89 | LastTime : string; 90 | TotalTime : string; 91 | MailAdress : string; 92 | CreateIP : string; 93 | CreateTime : string; 94 | RegisterIP : string; 95 | RegisterTime : string; 96 | isChecked : string; 97 | isVisible : string; 98 | picture_png : string; 99 | end; 100 | 101 | 102 | jobType = record // job server record 103 | idjobs : string ; 104 | inquirer : string ; 105 | inqIP : string ; 106 | inqTime : string ; 107 | idUser : string ; 108 | Action : string ; 109 | Intervall : string ; 110 | Result : string ; 111 | Status : string ; 112 | StatusMsg : string ; 113 | context : String; 114 | end; 115 | 116 | 117 | procedure cpyForumInfo( CONST qry:TSQLQuery; VAR memFrm:ForInfType ); 118 | procedure cpyTopicInfo( CONST qry:TSQLQuery; VAR memFrm:TopInfType ); 119 | procedure cpyPostInfo ( CONST qry:TSQLQuery; VAR PstFrm:PstInfType ); 120 | procedure cpyUsrInfo ( CONST qry:TSQLQuery; VAR usrFrm:usrInfType ); 121 | procedure cpySessInfo ( CONST qry:TSQLQuery; VAR SessFrm:sessInfType ); 122 | procedure cpyJobInfo ( CONST qry:TSQLQuery; VAR myJob:jobType ); 123 | 124 | function job_insert ( CONST conn: TMySQL55Connection; CONST myJob:JobType ): String; 125 | 126 | procedure ReadUsr ( CONST conn: TMySQL55Connection; CONST sUsr:string; VAR usrFrm:usrInfType ); 127 | function User_insert ( CONST conn: TMySQL55Connection; CONST usrFrm:usrInfType ): String; 128 | function updUser ( CONST conn: TMySQL55Connection; CONST usrFrm:usrInfType ): String; 129 | function count_usr_themes( CONST conn: TMySQL55Connection; CONST usrRec: usrInfType ): String; 130 | function count_usr_posts( CONST conn: TMySQL55Connection; CONST usrRec: usrInfType ): String; 131 | 132 | Function Upd_Forum ( CONST conn: TMySQL55Connection; CONST memFrm:ForInfType ): STRING ; 133 | procedure ReadForum ( CONST conn: TMySQL55Connection; CONST idFrm:string; VAR usrFrm:ForInfType ); 134 | 135 | procedure sesn_Read ( CONST conn: TMySQL55Connection; VAR sesnRec: sessInfType ); 136 | function sesn_count ( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 137 | function sesn_close ( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 138 | function sesn_insert ( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 139 | function sesn_update ( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 140 | 141 | procedure Topic_Read ( CONST conn: TMySQL55Connection; VAR memFrm: TopInfType ); 142 | Function Topic_Update( CONST conn: TMySQL55Connection; CONST memTpc: TopInfType ): STRING ; 143 | function topic_insert( CONST conn: TMySQL55Connection; CONST memFrm:TopInfType ): String; 144 | 145 | Function posts_Update( CONST conn: TMySQL55Connection; CONST memFrm: PstInfType ): STRING ; 146 | function posts_insert( CONST conn: TMySQL55Connection; CONST memFrm: PstInfType ): String; 147 | Function posts_Delete( CONST conn: TMySQL55Connection; CONST id:String ): STRING ; 148 | procedure posts_read ( CONST conn: TMySQL55Connection; VAR memFrm:PstInfType ); 149 | Function posts_Count ( CONST conn: TMySQL55Connection; CONST dStart: String ): STRING ; 150 | 151 | Function GetContent (CONST conn: TMySQL55Connection; CONST sSearch:String ): STRING ; 152 | Function GetSetting (CONST conn : TMySQL55Connection; CONST inStrg: string): string; 153 | 154 | implementation 155 | 156 | 157 | Function GetSetting(CONST conn : TMySQL55Connection; CONST inStrg: string): string; 158 | VAR 159 | query : TSQLQuery; 160 | 161 | begin 162 | 163 | // query 164 | query := TSQLQuery.Create(nil); 165 | query.DataBase := conn; 166 | query.SQL.Text := 'select * from dbpara where qName="' + TRIM( inStrg ) + '"'; 167 | query.Open; 168 | 169 | if query.EOF then 170 | begin 171 | query.active := false; 172 | query.free; 173 | exit; 174 | end; 175 | 176 | if query.Fields[5].AsInteger <> 0 then 177 | GetSetting := decrypt( query.Fields[4].AsString ) 178 | else 179 | GetSetting := query.Fields[4].AsString; 180 | 181 | query.active := false; 182 | query.free; 183 | 184 | end; 185 | 186 | ////////////////////////////////////////////////////////// 187 | // sample calls : GetContent(conn, 'bad_de' ): string; 188 | // GetContent(conn, 'bad_en' ): string; 189 | 190 | Function GetContent( CONST conn: TMySQL55Connection; CONST sSearch:String ): STRING ; 191 | VAR 192 | query : TSQLQuery; 193 | 194 | begin 195 | GetContent := 'none'; 196 | // query 197 | query := TSQLQuery.Create(nil); 198 | query.DataBase := conn; 199 | query.SQL.Text := 'select * from contval where cName="' + TRIM( sSearch ) + '"'; 200 | query.Open; 201 | 202 | if query.EOF then 203 | begin 204 | query.active := false; 205 | query.Free; 206 | exit; 207 | end; 208 | 209 | if query.Fields[5].AsInteger <> 0 then 210 | GetContent := decrypt( query.FieldByName('cValue').AsString ) 211 | else 212 | GetContent := query.FieldByName('cValue').AsString ; 213 | 214 | query.active := false; 215 | query.Free; 216 | 217 | end; 218 | 219 | procedure cpyJobInfo ( CONST qry:TSQLQuery; VAR myJob:jobType ); 220 | begin 221 | myJob.idjobs := qry.FieldByName('idjobs').AsString; 222 | myJob.inquirer := qry.FieldByName('inquirer').AsString; 223 | myJob.inqIP := qry.FieldByName('inqIP').AsString; 224 | myJob.inqTime := qry.FieldByName('inqTime').AsString; 225 | myJob.idUser := qry.FieldByName('idUser').AsString; 226 | myJob.Action := qry.FieldByName('Action').AsString; 227 | myJob.Intervall := qry.FieldByName('Intervall').AsString; 228 | myJob.Result := qry.FieldByName('Result').AsString; 229 | myJob.Status := qry.FieldByName('Status').AsString; 230 | myJob.StatusMsg := qry.FieldByName('StatusMsg').AsString; 231 | myJob.context := qry.FieldByName('context').AsString; 232 | end; 233 | 234 | procedure cpyUsrInfo ( CONST qry:TSQLQuery; VAR usrFrm:usrInfType ); 235 | begin 236 | usrFrm.iduser := qry.FieldByName('iduser').AsString; 237 | usrFrm.Name := qry.FieldByName('Name').AsString; 238 | usrFrm.pwd := decrypt( qry.FieldByName('pwd').AsString ); 239 | usrFrm.LastTime := qry.FieldByName('LastTime').AsString; 240 | usrFrm.TotalTime := qry.FieldByName('TotalTime').AsString; 241 | usrFrm.MailAdress := qry.FieldByName('MailAdress').AsString; 242 | usrFrm.CreateIP := qry.FieldByName('CreateIP').AsString; 243 | usrFrm.CreateTime := qry.FieldByName('CreateTime').AsString; 244 | usrFrm.RegisterIP := qry.FieldByName('RegisterIP').AsString; 245 | usrFrm.RegisterTime := qry.FieldByName('RegisterTime').AsString; 246 | usrFrm.isChecked := qry.FieldByName('isChecked').AsString; 247 | usrFrm.isVisible := qry.FieldByName('isVisible').AsString; 248 | usrFrm.picture_png := qry.FieldByName('picture_png').AsString; 249 | 250 | end; 251 | 252 | procedure cpyPostInfo( CONST qry:TSQLQuery; VAR PstFrm:PstInfType ); 253 | begin 254 | PstFrm.id := qry.FieldByName('id').AsString; 255 | PstFrm.topic_id := qry.FieldByName('topic_id').AsString; 256 | PstFrm.forum_id := qry.FieldByName('forum_id').AsString; 257 | PstFrm.user_id := qry.FieldByName('user_id').AsString; 258 | PstFrm.poster_ip := qry.FieldByName('poster_ip').AsString; 259 | PstFrm.post_time := qry.FieldByName('post_time').AsString; 260 | PstFrm.post_subject := qry.FieldByName('post_subject').AsString; 261 | PstFrm.post_text := qry.FieldByName('post_text').AsString; 262 | PstFrm.post_postcount := qry.FieldByName('post_postcount').AsString; 263 | PstFrm.post_alpha := qry.FieldByName('post_alpha').AsString; 264 | PstFrm.post_size := qry.FieldByName('post_size').AsString; 265 | PstFrm.post_edit_time := qry.FieldByName('post_edit_time').AsString; 266 | PstFrm.post_edit_reason := qry.FieldByName('post_edit_reason').AsString; 267 | PstFrm.post_edit_user := qry.FieldByName('post_edit_user').AsString; 268 | PstFrm.post_edit_count := qry.FieldByName('post_edit_count').AsString; 269 | PstFrm.post_edit_locked := qry.FieldByName('post_edit_locked').AsString; 270 | end; 271 | 272 | 273 | procedure cpyTopicInfo( CONST qry:TSQLQuery; VAR memFrm:TopInfType ); 274 | begin 275 | memFrm.id := qry.FieldByName('id').AsString; 276 | memFrm.forum_id := qry.FieldByName('forum_id').AsString; 277 | memFrm.title := qry.FieldByName('title').AsString; 278 | memFrm.topic_text := qry.FieldByName('topic_text').AsString; 279 | memFrm.poster := qry.FieldByName('poster').AsString; 280 | memFrm.poster_name := qry.FieldByName('poster_name').AsString; 281 | memFrm.ctime := qry.FieldByName('ctime').AsString; 282 | memFrm.time_limit := qry.FieldByName('time_limit').AsString; 283 | memFrm.views := qry.FieldByName('views').AsString; 284 | memFrm.replies := qry.FieldByName('replies').AsString; 285 | memFrm.replies_real := qry.FieldByName('replies_real').AsString; 286 | memFrm.first_post_id := qry.FieldByName('first_post_id').AsString; 287 | memFrm.first_poster_name := qry.FieldByName('first_poster_name').AsString; 288 | memFrm.last_post_id := qry.FieldByName('last_post_id').AsString; 289 | memFrm.last_poster_id := qry.FieldByName('last_poster_id').AsString; 290 | memFrm.last_poster_name := qry.FieldByName('last_poster_name').AsString; 291 | memFrm.last_post_subject := qry.FieldByName('last_post_subject').AsString; 292 | memFrm.last_post_time := qry.FieldByName('last_post_time').AsString; 293 | memFrm.last_view_time := qry.FieldByName('last_view_time').AsString; 294 | end; 295 | 296 | 297 | procedure cpyForumInfo( CONST qry:TSQLQuery; VAR memFrm:ForInfType ); 298 | begin 299 | memFrm.id := qry.FieldByName('id').AsString; 300 | memFrm.fName := qry.FieldByName('fname').AsString; 301 | memFrm.fDesc := qry.FieldByName('fdesc').AsString; 302 | memFrm.fdesc_bitfield := qry.FieldByName('fdesc_bitfield').AsString; 303 | memFrm.fdesc_uid := qry.FieldByName('fdesc_uid').AsString; 304 | memFrm.topics_per_page := qry.FieldByName('topics_per_page').AsString; 305 | memFrm.posts := qry.FieldByName('posts').AsString; 306 | memFrm.topics := qry.FieldByName('topics').AsString; 307 | memFrm.topics_real := qry.FieldByName('topics_real').AsString; 308 | memFrm.last_post_id := qry.FieldByName('last_post_id').AsString; 309 | memFrm.last_poster_id := qry.FieldByName('last_poster_id').AsString; 310 | memFrm.last_post_subject := qry.FieldByName('last_post_subject').AsString; 311 | memFrm.last_post_time := qry.FieldByName('last_post_time').AsString; 312 | memFrm.last_poster_name := qry.FieldByName('last_poster_name').AsString; 313 | end; 314 | 315 | 316 | procedure cpySessInfo ( CONST qry:TSQLQuery; VAR SessFrm:sessInfType ); 317 | begin 318 | SessFrm.rid := qry.FieldByName('rid').AsString; 319 | SessFrm.id := qry.FieldByName('id').AsString; 320 | SessFrm.user_id := qry.FieldByName('user_id').AsString; 321 | SessFrm.forum_id := qry.FieldByName('forum_id').AsString; 322 | SessFrm.is_active := qry.FieldByName('is_active').AsString; 323 | SessFrm.last_forum := qry.FieldByName('last_forum').AsString; 324 | SessFrm.browser := qry.FieldByName('browser').AsString; 325 | SessFrm.sip := qry.FieldByName('sip').AsString; 326 | SessFrm.sLat := qry.FieldByName('sLat').AsString; 327 | SessFrm.sLong := qry.FieldByName('sLong').AsString; 328 | SessFrm.latitude := qry.FieldByName('latitude').AsString; 329 | SessFrm.longitude := qry.FieldByName('longitude').AsString; 330 | SessFrm.accuracy := qry.FieldByName('accuracy').AsString; 331 | SessFrm.forwarded_for := qry.FieldByName('forwarded_for').AsString; 332 | SessFrm.v_order := qry.FieldByName('v_order').AsString; 333 | SessFrm.v_page := qry.FieldByName('v_page').AsString; 334 | SessFrm.v_rec := qry.FieldByName('v_rec').AsString; 335 | SessFrm.v_eof := qry.FieldByName('v_eof').AsString; 336 | SessFrm.viewonline := qry.FieldByName('viewonline').AsString; 337 | SessFrm.autologin := qry.FieldByName('autologin').AsString; 338 | SessFrm.admin := qry.FieldByName('admin').AsString; 339 | SessFrm.lastsearch := qry.FieldByName('lastsearch').AsString; 340 | SessFrm.lastlogin := qry.FieldByName('lastlogin').AsString; 341 | SessFrm.last_post_cnt := qry.FieldByName('last_post_cnt').AsString; 342 | SessFrm.login := qry.FieldByName('login').AsString; 343 | SessFrm.logout := qry.FieldByName('logout').AsString; 344 | end; 345 | 346 | procedure ReadForum(CONST conn:TMySQL55Connection; CONST idFrm:string; VAR usrFrm:ForInfType ); 347 | VAR 348 | query2 : TSQLQuery; 349 | 350 | begin 351 | query2 := TSQLQuery.Create(nil); 352 | query2.DataBase := conn; 353 | query2.SQL.Text := 'select * from forums ' + idFrm ; 354 | query2.Open; 355 | 356 | if not query2.eof then cpyForumInfo( query2, usrFrm ); 357 | query2.active := false; 358 | query2.Free; 359 | 360 | 361 | end; 362 | 363 | procedure ReadUsr(CONST conn:TMySQL55Connection; CONST sUsr:string; VAR usrFrm:usrInfType ); 364 | VAR 365 | query2 : TSQLQuery; 366 | 367 | begin 368 | query2 := TSQLQuery.Create(nil); 369 | query2.DataBase := conn; 370 | query2.SQL.Text := 'select * from user ' + sUsr ; 371 | query2.Open; 372 | 373 | if not query2.eof then 374 | cpyUsrInfo( query2, usrFrm ) 375 | else 376 | usrFrm.iduser:= ''; 377 | 378 | query2.active := false; 379 | query2.Free; 380 | 381 | 382 | end; 383 | 384 | Function Upd_Forum( CONST conn: TMySQL55Connection; CONST memFrm: ForInfType ): STRING ; 385 | VAR 386 | query2 : TSQLQuery; 387 | sQry : STRING; 388 | 389 | begin 390 | sQry := 'UPDATE forums SET fname = "%%1", fdesc = "%%2", fdesc_bitfield = "%%3", fdesc_uid = %%4, topics_per_page = %%5, posts = %%6, '+ 391 | 'topics = %%7, topics_real = %%8, last_post_id = %%9, last_poster_id = %%A, last_post_subject = "%%B", last_post_time = now(), last_poster_name = "%%C" ' + 392 | 'WHERE id = %%D;'; 393 | 394 | sQry := sUpdate( sQry, '%%1', memFrm.fName ); 395 | sQry := sUpdate( sQry, '%%2', memFrm.fDesc ); 396 | sQry := sUpdate( sQry, '%%3', memFrm.fdesc_bitfield ); 397 | sQry := sUpdate( sQry, '%%4', memFrm.fdesc_uid ); 398 | sQry := sUpdate( sQry, '%%5', memFrm.topics_per_page ); 399 | sQry := sUpdate( sQry, '%%6', memFrm.posts ); 400 | sQry := sUpdate( sQry, '%%7', memFrm.topics ); 401 | sQry := sUpdate( sQry, '%%8', memFrm.topics_real ); 402 | sQry := sUpdate( sQry, '%%9', memFrm.last_post_id ); 403 | sQry := sUpdate( sQry, '%%A', memFrm.last_poster_id ); 404 | sQry := sUpdate( sQry, '%%B', memFrm.last_post_subject ); 405 | sQry := sUpdate( sQry, '%%C', memFrm.last_poster_name ); 406 | sQry := sUpdate( sQry, '%%D', memFrm.ID); 407 | 408 | query2 := TSQLQuery.Create(nil); 409 | query2.DataBase := conn; 410 | query2.SQL.Text := sQry; 411 | try 412 | query2.ExecSQL; 413 | conn.Transaction.Commit; 414 | except 415 | on e: Exception do Upd_Forum := e.Message + query2.SQL.Text; 416 | end; 417 | 418 | query2.active := False; 419 | query2.Free; 420 | 421 | end; 422 | 423 | 424 | function updUser( CONST conn: TMySQL55Connection; CONST usrFrm:usrInfType ): String; 425 | VAR 426 | query2 : TSQLQuery; 427 | sQry, d1, d2, d3 : STRING; 428 | 429 | begin 430 | 431 | // normalize datetime 432 | d1 := usrFrm.LastTime; 433 | d2 := usrFrm.CreateTime; 434 | d3 := usrFrm.RegisterTime; 435 | if d1 = '' then d1 := DateTimeToStr (now) ; 436 | if d2 = '' then d2 := d1; 437 | if d3 = '' then d3 := d1; 438 | d1 := FormatDateTime(sqlDate, StrToDateTime(d1)); 439 | d2 := FormatDateTime(sqlDate, StrToDateTime(d2)); 440 | d3 := FormatDateTime(sqlDate, StrToDateTime(d3)); 441 | 442 | // build query 443 | sQry := 'UPDATE user SET Name = "%%1", pwd = "%%2", LastTime= "%%3", TotalTime=%%4, MailAdress="%%5", CreateIP="%%6", CreateTime="%%7", ' + 444 | 'RegisterIP="%%8", RegisterTime="%%9", isChecked="%%A", isVisible="%%B"'; 445 | if usrFrm.picture_png <> '' then sQry += ', picture_png=x''%%C'' '; 446 | sQry += ' WHERE iduser= %%D'; 447 | 448 | 449 | sQry := sUpdate( sQry, '%%1', usrFrm.Name ); 450 | sQry := sUpdate( sQry, '%%2', encrypt(usrFrm.pwd) ); 451 | sQry := sUpdate( sQry, '%%3', d1 ); 452 | sQry := sUpdate( sQry, '%%4', usrFrm.TotalTime ); 453 | sQry := sUpdate( sQry, '%%5', usrFrm.MailAdress ); 454 | sQry := sUpdate( sQry, '%%6', usrFrm.CreateIP ); 455 | sQry := sUpdate( sQry, '%%7', d2 ); 456 | sQry := sUpdate( sQry, '%%8', usrFrm.RegisterIP ); 457 | sQry := sUpdate( sQry, '%%9', d3 ); 458 | sQry := sUpdate( sQry, '%%A', usrFrm.isChecked ); 459 | sQry := sUpdate( sQry, '%%B', usrFrm.isVisible ); 460 | if usrFrm.picture_png <> '' then 461 | sQry:=sUpdate(sQry, '%%C', usrFrm.picture_png ); 462 | sQry := sUpdate( sQry, '%%D', usrFrm.iduser ); 463 | 464 | // write to db 465 | query2 := TSQLQuery.Create(nil); 466 | query2.DataBase := conn; 467 | query2.SQL.Text := sQry; 468 | try 469 | query2.ExecSQL; 470 | conn.Transaction.Commit; 471 | except 472 | on e: Exception do updUser := e.Message + CHR(13) + sQry; 473 | end; 474 | 475 | query2.active := False; 476 | query2.Free; 477 | 478 | end; 479 | 480 | 481 | 482 | function posts_insert( CONST conn: TMySQL55Connection; CONST memFrm: PstInfType ): String; 483 | VAR 484 | i: integer; 485 | sTmp : string; 486 | query2 : TSQLQuery; 487 | 488 | begin 489 | posts_insert := ''; 490 | query2 := TSQLQuery.Create(nil); 491 | query2.DataBase := conn; 492 | query2.SQL.Text := 'INSERT INTO posts ( topic_id, forum_id, user_id, poster_ip, post_subject, post_text, post_alpha, post_size )' + 493 | 'VALUES ( ' + memFrm.topic_id + ', ' + memFrm.forum_id + ', ' + memFrm.user_id + ', "' + 494 | memFrm.poster_ip + '", "' + memFrm.post_subject + '", x' + #39 + StrToHex(memfrm.post_text) + #39 + ', "' + 495 | memfrm.post_alpha + '", ' + memfrm.post_size +');'; 496 | try 497 | query2.ExecSQL; 498 | conn.Transaction.Commit; 499 | except 500 | on e: Exception do posts_insert := 'posts_insert ' + e.Message + '--' + query2.SQL.Text; 501 | end; 502 | 503 | query2.active := False; 504 | query2.Free; 505 | end; 506 | 507 | function User_insert( CONST conn: TMySQL55Connection; CONST usrFrm:usrInfType ): String; 508 | VAR 509 | query2 : TSQLQuery; 510 | 511 | begin 512 | User_insert := '' ; 513 | query2 := TSQLQuery.Create(nil); 514 | query2.DataBase := conn; 515 | Query2.SQL.Text := 'INSERT INTO user (Name, pwd, LastTime, TotalTime, MailAdress, CreateIP, CreateTime ) VALUES ("' + 516 | usrFrm.Name + '", "' + usrFrm.pwd + '", now(), 0, "' + usrFrm.MailAdress + '", "' + usrFrm.RegisterIP + '", now() )'; 517 | try 518 | query2.ExecSQL; 519 | conn.Transaction.Commit; 520 | except 521 | on e: Exception do User_insert := 'User_insert ' + e.Message; 522 | end; 523 | 524 | query2.active := False; 525 | query2.Free; 526 | 527 | end; 528 | 529 | function topic_insert( CONST conn: TMySQL55Connection; CONST memFrm: TopInfType ): String; 530 | VAR 531 | query2 : TSQLQuery; 532 | 533 | begin 534 | topic_insert := ''; 535 | query2 := TSQLQuery.Create(nil); 536 | query2.DataBase := conn; 537 | query2.SQL.Text := 'INSERT INTO topics ( forum_id, title, topic_text, poster, poster_name, ctime ) ' + 538 | 'VALUES ( ' + memFrm.forum_id + ', "' + memFrm.title + '", x' + #39 + StrToHex(memFrm.topic_text) + #39 + ', ' + 539 | memFrm.poster + ', "' + memFrm.poster_name + '", now() );'; 540 | 541 | try 542 | query2.ExecSQL; 543 | conn.Transaction.Commit; 544 | except 545 | on e: Exception do topic_insert := 'topic_insert ' + e.Message; 546 | end; 547 | 548 | query2.active := False; 549 | query2.Free; 550 | 551 | end; 552 | 553 | 554 | ///////////////////////////////////////////////// 555 | // called on new session by sesn_insert 556 | // called on expired session by isSessionValid 557 | 558 | function sesn_close( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 559 | VAR 560 | query2 : TSQLQuery; 561 | sQry : STRING; 562 | 563 | begin 564 | 565 | sQry := 'UPDATE sessions ' + 566 | 'SET is_active="0", logout="' + FormatDateTime(sqlDate, now()) + '" ' + 567 | 'WHERE user_id="' + sesnRec.user_id + '";' ; 568 | query2 := TSQLQuery.Create(nil); 569 | query2.DataBase := conn; 570 | query2.SQL.Text := sQry; 571 | try 572 | query2.ExecSQL; 573 | conn.Transaction.Commit; 574 | except 575 | on e: Exception do sesn_close := 'sesn_close ' + e.Message; 576 | end; 577 | 578 | query2.active := False; 579 | query2.Free; 580 | end; 581 | 582 | function count_usr_posts( CONST conn: TMySQL55Connection; CONST usrRec: usrInfType ): String; 583 | VAR 584 | query2 : TSQLQuery; 585 | sQry : STRING; 586 | 587 | begin 588 | count_usr_posts := '0'; 589 | query2 := TSQLQuery.Create(nil); 590 | query2.DataBase := conn; 591 | query2.SQL.Text := 'select count(*) from posts where user_id=' + usrRec.iduser ; 592 | query2.Open; 593 | 594 | if not query2.eof then count_usr_posts := query2.Fields[0].AsString; 595 | query2.active := False; 596 | query2.Free; 597 | 598 | end; 599 | 600 | function count_usr_themes( CONST conn: TMySQL55Connection; CONST usrRec: usrInfType ): String; 601 | VAR 602 | query2 : TSQLQuery; 603 | sQry : STRING; 604 | 605 | begin 606 | count_usr_themes := '0'; 607 | query2 := TSQLQuery.Create(nil); 608 | query2.DataBase := conn; 609 | query2.SQL.Text := 'select count(*) from topics where poster=' + usrRec.iduser ; 610 | query2.Open; 611 | 612 | if not query2.eof then count_usr_themes := query2.Fields[0].AsString; 613 | query2.active := False; 614 | query2.Free; 615 | 616 | end; 617 | 618 | 619 | function sesn_count( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 620 | VAR 621 | query2 : TSQLQuery; 622 | sQry : STRING; 623 | 624 | begin 625 | sesn_count := '0'; 626 | query2 := TSQLQuery.Create(nil); 627 | query2.DataBase := conn; 628 | query2.SQL.Text := 'select count(*) from sessions where is_active ="1";'; 629 | query2.Open; 630 | 631 | if not query2.eof then sesn_count := query2.Fields[0].AsString; 632 | query2.active := False; 633 | query2.Free; 634 | 635 | end; 636 | 637 | 638 | 639 | 640 | function sesn_insert( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 641 | VAR 642 | query2 : TSQLQuery; 643 | s1,s2,s3,s4, s5 : String; 644 | 645 | begin 646 | // normalize paras - avoid blank 647 | s1 := iif( sesnRec.last_forum ='', '0', sesnRec.last_forum ); 648 | s2 := iif( sesnRec.latitude ='', '0', sesnRec.latitude); 649 | s3 := iif( sesnRec.longitude ='', '0', sesnRec.longitude ); 650 | s4 := iif( sesnRec.accuracy ='', '0', sesnRec.accuracy ); 651 | s5 := iif( sesnRec.lastlogin ='', 652 | FormatDateTime(sqlDate, now()), 653 | FormatDateTime(sqlDate, StrToDateTime(sesnRec.lastlogin))); 654 | 655 | // close all open sessions for user_id 656 | sesn_close( conn, sesnRec ); 657 | 658 | sesn_insert := ''; 659 | query2 := TSQLQuery.Create(nil); 660 | query2.DataBase := conn; 661 | query2.SQL.Text := 'INSERT INTO sessions ( id, user_id, forum_id, is_active, last_forum, browser, sip, sLat, sLong, latitude, longitude, ' + 662 | 'accuracy, v_order, v_page, v_rec, v_eof, lastlogin, last_post_cnt ) ' + 663 | 'VALUES ( "' + sesnRec.id + '", ' + sesnRec.user_id + ' ,' + sesnRec.forum_id + ' ,"' + sesnRec.is_active + '", ' + 664 | s1 + ', "' + sesnRec.browser + '", "' + sesnRec.sip + '", ' + sesnRec.sLat + ', ' + sesnRec.sLong + ' ,' + 665 | s2 + ', ' + s3 + ', ' + s4 + ', ' + sesnRec.v_order + ', ' + sesnRec.v_page + ', ' + sesnRec.v_rec + ', ' + 666 | sesnRec.v_eof + ', "' + s5 + '", ' + sesnRec.last_post_cnt + ');'; 667 | try 668 | query2.ExecSQL; 669 | conn.Transaction.Commit; 670 | except 671 | on e: Exception do sesn_insert := 'sesn_insert ' + e.Message; 672 | end; 673 | 674 | query2.active := False; 675 | query2.Free; 676 | 677 | end; 678 | 679 | 680 | function job_insert( CONST conn: TMySQL55Connection; CONST myJob:JobType ): String; 681 | VAR 682 | query2 : TSQLQuery; 683 | 684 | begin 685 | job_insert := ''; 686 | query2 := TSQLQuery.Create(nil); 687 | query2.DataBase := conn; 688 | query2.SQL.Text := 'INSERT INTO jobs ( inquirer, inqIP, inqTime, idUser, Action, Intervall, context ) VALUES ("' + 689 | myJob.inquirer + '", "' + myJob.inqIP + '", now(), ' + myJob.iduser +', "' + myJob.Action +'", ' + 690 | myJob.Intervall + ', "' + myJob.context + '" )'; 691 | try 692 | query2.ExecSQL; 693 | conn.Transaction.Commit; 694 | except 695 | on e: Exception do job_insert := 'job_insert ' + e.Message; 696 | end; 697 | 698 | query2.active := False; 699 | query2.Free; 700 | 701 | end; 702 | 703 | 704 | function sesn_update ( CONST conn: TMySQL55Connection; CONST sesnRec: sessInfType ): String; 705 | VAR 706 | query2 : TSQLQuery; 707 | sQry : STRING; 708 | 709 | begin 710 | sesn_update := ''; 711 | sQry := 'UPDATE sessions SET is_active=%%1, forum_id=%%2, last_forum=%%3, forwarded_for="%%4", v_order=%%5, v_page=%%6, v_rec=%%7, v_eof=%%8, lastsearch="%%9" WHERE id="' + sesnRec.id + '";' ; 712 | sQry := sUpdate( sQry, '%%1', sesnRec.is_active ); 713 | sQry := sUpdate( sQry, '%%2', sesnRec.forum_id ); 714 | sQry := sUpdate( sQry, '%%3', sesnRec.last_forum ); 715 | sQry := sUpdate( sQry, '%%4', sesnRec.forwarded_for ); 716 | sQry := sUpdate( sQry, '%%5', sesnRec.v_order); 717 | sQry := sUpdate( sQry, '%%6', sesnRec.v_page ); 718 | sQry := sUpdate( sQry, '%%7', sesnRec.v_rec ); 719 | sQry := sUpdate( sQry, '%%8', sesnRec.v_eof ); 720 | sQry := sUpdate( sQry, '%%9', sesnRec.lastsearch ); 721 | query2 := TSQLQuery.Create(nil); 722 | query2.DataBase := conn; 723 | query2.SQL.Text := sQry; 724 | try 725 | query2.ExecSQL; 726 | conn.Transaction.Commit; 727 | except 728 | on e: Exception do sesn_update := query2.SQL.Text + ' -- sesn_update --' + e.Message; 729 | end; 730 | 731 | query2.active := False; 732 | query2.Free; 733 | 734 | end; 735 | 736 | 737 | procedure sesn_Read(CONST conn:TMySQL55Connection; VAR sesnRec: sessInfType ); 738 | VAR 739 | query2 : TSQLQuery; 740 | 741 | begin 742 | query2 := TSQLQuery.Create(nil); 743 | query2.DataBase := conn; 744 | query2.SQL.Text := 'SELECT * FROM sessions WHERE id="' + sesnRec.id + '";'; 745 | query2.Open; 746 | 747 | if not query2.eof then cpySessInfo ( query2, sesnRec ); 748 | query2.active := false; 749 | query2.Free; 750 | 751 | end; 752 | 753 | procedure posts_read( CONST conn: TMySQL55Connection; VAR memFrm:PstInfType ); 754 | VAR 755 | query2 : TSQLQuery; 756 | 757 | begin 758 | query2 := TSQLQuery.Create(nil); 759 | query2.DataBase := conn; 760 | query2.SQL.Text := 'SELECT * FROM posts WHERE id="' + memFrm.id + '";'; 761 | query2.Open; 762 | 763 | if not query2.eof then 764 | cpyPostInfo( Query2, memFrm ) 765 | else 766 | memFrm.id := ''; 767 | 768 | query2.active := false; 769 | query2.Free; 770 | 771 | end; 772 | 773 | 774 | Function posts_Delete( CONST conn: TMySQL55Connection; CONST id:String ): STRING ; 775 | VAR 776 | query2 : TSQLQuery; 777 | 778 | begin 779 | posts_Delete := ''; 780 | query2 := TSQLQuery.Create(nil); 781 | query2.DataBase := conn; 782 | query2.SQL.Text := 'DELETE FROM posts WHERE id=' + id + ';'; 783 | try 784 | query2.ExecSQL; 785 | conn.Transaction.Commit; 786 | except 787 | on e: Exception do posts_Delete := e.Message + query2.SQL.Text; 788 | end; 789 | 790 | query2.active := False; 791 | query2.Free; 792 | 793 | end; 794 | 795 | 796 | Function posts_Count( CONST conn: TMySQL55Connection; CONST dStart: String ): STRING ; 797 | VAR 798 | query2 : TSQLQuery; 799 | 800 | begin 801 | posts_Count := '0'; 802 | query2 := TSQLQuery.Create(nil); 803 | query2.DataBase := conn; 804 | query2.SQL.Text := 'select count(*) from posts where post_time > "'+ 805 | FormatDateTime(sqlDate, StrToDateTime(dStart)) + '";'; 806 | query2.Open; 807 | 808 | if not query2.eof then posts_Count := query2.Fields[0].AsString; 809 | query2.active := False; 810 | query2.Free; 811 | 812 | end; 813 | 814 | procedure Topic_Read(CONST conn:TMySQL55Connection; VAR memFrm: TopInfType ); 815 | VAR 816 | query2 : TSQLQuery; 817 | 818 | begin 819 | 820 | if memFrm.id = '' then exit; 821 | query2 := TSQLQuery.Create(nil); 822 | query2.DataBase := conn; 823 | query2.SQL.Text := 'SELECT * FROM topics where id=' + memFrm.id ; 824 | query2.Open; 825 | 826 | if not query2.eof then 827 | cpyTopicInfo( Query2, memFrm ) 828 | else 829 | memFrm.id := ''; 830 | 831 | query2.active := false; 832 | query2.Free; 833 | 834 | end; 835 | 836 | 837 | Function posts_Update( CONST conn: TMySQL55Connection; CONST memFrm: PstInfType ): STRING ; 838 | VAR 839 | query2 : TSQLQuery; 840 | d1, d2, sQry: STRING; 841 | 842 | begin 843 | 844 | posts_Update := ''; 845 | // normalize datetime 846 | d1 := memFrm.post_time; 847 | d2 := memFrm.post_edit_time; 848 | if d1 = '' then d1 := DateTimeToStr (now) ; 849 | if d2 = '' then d2 := d1; 850 | d1 := FormatDateTime(sqlDate, StrToDateTime(d1)); 851 | d2 := FormatDateTime(sqlDate, StrToDateTime(d2)); 852 | // make query string post_text=''%%7'' changed to post_text=%%7 853 | sQry := 'UPDATE posts SET topic_id= %%1, forum_id=%%2, user_id=%%3, poster_ip="%%4", post_time="%%5", post_subject="%%6", post_text=%%7, ' + 854 | 'post_postcount= %%8, post_alpha="%%9", post_size=%%A, post_edit_time="%%B", post_edit_reason="", post_edit_user=%%D, post_edit_count=%%E, post_edit_locked="%%F" ' + 855 | 'WHERE id=%%G;'; 856 | 857 | sQry := sUpdate( sQry, '%%1', memFrm.topic_id ); 858 | sQry := sUpdate( sQry, '%%2', memFrm.forum_id ); 859 | sQry := sUpdate( sQry, '%%3', memFrm.user_id ); 860 | sQry := sUpdate( sQry, '%%4', memFrm.poster_ip ); 861 | sQry := sUpdate( sQry, '%%5', d1 ); 862 | sQry := sUpdate( sQry, '%%6', memFrm.post_subject ); 863 | // sQry := sUpdate( sQry, '%%7', memFrm.post_text ); 864 | sQry := sUpdate( sQry, '%%7', 'x' + #39 + StrToHex(memFrm.post_text) + #39 ); 865 | sQry := sUpdate( sQry, '%%8', memFrm.post_postcount ); 866 | 867 | sQry := sUpdate( sQry, '%%9', memFrm.post_alpha ); 868 | sQry := sUpdate( sQry, '%%A', memFrm.post_size ); 869 | 870 | sQry := sUpdate( sQry, '%%B', d2 ); 871 | sQry := sUpdate( sQry, '%%C', memFrm.post_edit_reason ); 872 | sQry := sUpdate( sQry, '%%D', memFrm.post_edit_user ); 873 | sQry := sUpdate( sQry, '%%E', memFrm.post_edit_count ); 874 | sQry := sUpdate( sQry, '%%F', memFrm.post_edit_locked); 875 | sQry := sUpdate( sQry, '%%G', memFrm.id ); 876 | 877 | query2 := TSQLQuery.Create(nil); 878 | query2.DataBase := conn; 879 | query2.SQL.Text := sQry; 880 | try 881 | query2.ExecSQL; 882 | conn.Transaction.Commit; 883 | except 884 | on e: Exception do posts_Update := e.Message + query2.SQL.Text; 885 | end; 886 | 887 | query2.active := False; 888 | query2.Free; 889 | 890 | end; 891 | 892 | Function Topic_Update( CONST conn: TMySQL55Connection; CONST memTpc: TopInfType ): STRING ; 893 | VAR 894 | query2 : TSQLQuery; 895 | d1, d2, d3, d4, sQry : STRING; 896 | 897 | begin 898 | 899 | Topic_Update := ''; 900 | // normalize datetime 901 | d1 := memTpc.cTime; 902 | d2 := memTpc.time_limit; 903 | d3 := memTpc.last_post_time; 904 | d4 := memTpc.last_view_time; 905 | if d1 = '' then d1 := DateTimeToStr (now) ; 906 | if d2 = '' then d2 := '30.12.2099 00:00:00'; 907 | if d3 = '' then d3 := d1; 908 | if d4 = '' then d4 := d1; 909 | d1 := FormatDateTime(sqlDate, StrToDateTime(d1)); 910 | d2 := FormatDateTime(sqlDate, StrToDateTime(d2)); 911 | d3 := FormatDateTime(sqlDate, StrToDateTime(d3)); 912 | d4 := FormatDateTime(sqlDate, StrToDateTime(d4)); 913 | 914 | // make query string Test: topic_text=%%3 instead of topic_text="%%3", 915 | sQry := 'UPDATE topics SET forum_id= %%1, title="%%2", topic_text=%%3, poster=%%4, poster_name="%%5", ctime= "%%6", ' + 916 | 'time_limit="%%7", views=%%8, replies=%%9, replies_real=%%A, first_post_id=%%B, first_poster_name="%%C", last_post_id=%%D, ' + 917 | 'last_poster_id=%%E, last_poster_name="%%F", last_post_subject="%%G", last_post_time="%%H", last_view_time="%%I" ' + 918 | 'WHERE id = %%J' ; 919 | 920 | sQry := sUpdate( sQry, '%%1', memTpc.forum_id ); 921 | sQry := sUpdate( sQry, '%%2', memTpc.title ); 922 | // sQry := sUpdate( sQry, '%%3', memTpc.topic_text ); 923 | sQry := sUpdate( sQry, '%%3', 'x' + #39 + StrToHex(memTpc.topic_text) + #39 ); 924 | sQry := sUpdate( sQry, '%%4', memTpc.poster ); 925 | sQry := sUpdate( sQry, '%%5', memTpc.poster_name ); 926 | sQry := sUpdate( sQry, '%%6', d1 ); 927 | sQry := sUpdate( sQry, '%%7', d2 ); 928 | sQry := sUpdate( sQry, '%%8', memTpc.views ); 929 | sQry := sUpdate( sQry, '%%9', memTpc.replies ); 930 | sQry := sUpdate( sQry, '%%A', memTpc.replies_real ); 931 | sQry := sUpdate( sQry, '%%B', memTpc.first_post_id ); 932 | sQry := sUpdate( sQry, '%%C', memTpc.first_poster_name ); 933 | sQry := sUpdate( sQry, '%%D', memTpc.last_post_id); 934 | sQry := sUpdate( sQry, '%%E', memTpc.last_poster_id ); 935 | sQry := sUpdate( sQry, '%%F', memTpc.last_poster_name ); 936 | sQry := sUpdate( sQry, '%%G', memTpc.last_post_subject ); 937 | sQry := sUpdate( sQry, '%%H', d3 ); 938 | sQry := sUpdate( sQry, '%%I', d4 ); 939 | sQry := sUpdate( sQry, '%%J', memTpc.id ); 940 | 941 | query2 := TSQLQuery.Create(nil); 942 | query2.DataBase := conn; 943 | query2.SQL.Text := sQry; 944 | try 945 | query2.ExecSQL; 946 | conn.Transaction.Commit; 947 | except 948 | on e: Exception do Topic_Update := e.Message + query2.SQL.Text; 949 | end; 950 | 951 | query2.active := False; 952 | query2.Free; 953 | 954 | end; 955 | 956 | end. 957 | 958 | -------------------------------------------------------------------------------- /menu.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_cgi 3 | // author : Ralph Berger 4 | // file : menu.pas 5 | // erstellt : 28.02.14 6 | // modified : RB - 21.03.2014 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | // tested : yes 9 | 10 | unit Menu; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses 17 | Classes, SysUtils, Variants, synacode, FmtBCD, mysql55conn, sqldb, blowcryp, mapping ; 18 | 19 | CONST 20 | PageItems = 5; 21 | cgiPath = '/fcgi-bin/bbs/'; 22 | err_page= 'bbs_error.html'; 23 | MenuS_1 = '
  • TeamBBS Forum
  • '; 24 | MenuS_1i= '
  • TeamBBS Forum
  • '; 25 | MenuS_2 = '
  • Abmelden
  • ' + 26 | '
  • Meine Nachrichten
  • '; 27 | 28 | FootStr = ''; 442 | 443 | end; 444 | 445 | end. 446 | -------------------------------------------------------------------------------- /myaccnt.pas: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // file : myAccnt.pas 3 | // called as 'cgi1/myacc' 4 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 5 | 6 | unit myAccnt; 7 | 8 | {$mode objfpc}{$H+} 9 | 10 | interface 11 | 12 | uses 13 | BrookAction, BrookFCLFCGIBroker, BrookConsts, BrookUtils, HTTPDefs, Classes, SysUtils, 14 | Variants, FmtBCD, sqldb, blowcryp, mapping, menu; 15 | 16 | type 17 | TMyAccnt = class(TBrookAction) 18 | public 19 | procedure Get; override; 20 | procedure Post; override; 21 | end; 22 | 23 | implementation 24 | 25 | procedure TMyAccnt.Get; 26 | VAR 27 | sMenu, sRet : String; 28 | myPara : ParaType; 29 | usrFrm1: usrInfType ; 30 | 31 | 32 | begin 33 | // check session 34 | myPara.VSession := Params.Values['sesn']; 35 | mypara.sip:= TheRequest.RemoteAddress; 36 | if NOT isSessionValid( mypara ) then 37 | begin 38 | Render(err_page, [myPara.lastError]); 39 | exit; 40 | end; 41 | 42 | 43 | // render record 44 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + inttostr(myPara.userID), usrFrm1 ); 45 | sRet := sUpdate( accntEdt, '%%1', usrFrm1.Name ); 46 | sRet := sUpdate( sRet, '%%2', usrFrm1.MailAdress ); 47 | sRet := sUpdate( sRet, '%%3', usrFrm1.pwd ); 48 | sRet := sUpdate( sRet, '%%4', usrFrm1.pwd ); 49 | sRet := sUpdate( sRet, '%%5', showUsrImage(usrFrm1) ); 50 | if usrFrm1.isVisible = 'False' then 51 | sRet := sUpdate( sRet, '%%6', ' ' ) 52 | else 53 | sRet := sUpdate( sRet, '%%6', 'checked ="true"' ); 54 | 55 | sRet := sUpdate( sRet, '%%7', mypara.VSession ); 56 | 57 | mypara.sCmd := '1'; 58 | sMenu := make_Header( myPara ) ; 59 | // don't show navi buttons 60 | mypara.sCmd := '0'; 61 | Render('bbs_myacc.html', [sMenu, 62 | sRet, 63 | make_Footer(BrookFCLFCGIBroker.conn,mypara) ]); 64 | 65 | end; 66 | 67 | 68 | 69 | 70 | procedure TMyAccnt.Post; 71 | VAR 72 | i : integer; 73 | vPWD2, vagb, sRet : String; 74 | myPara : ParaType; 75 | usrFrm : usrInfType ; 76 | usrFrm1: usrInfType ; 77 | Stream : TMemoryStream; 78 | VFormItem: TUploadedFile; 79 | 80 | 81 | Begin 82 | vagb := Fields.Values['agb']; 83 | vPWD2:= Fields.Values['password_confirm']; 84 | 85 | usrFrm.Name := Fields.Values['usr_name']; 86 | usrFrm.MailAdress := Fields.Values['email']; 87 | usrFrm.pwd := Fields.Values['password']; 88 | usrFrm.isVisible := Fields.Values['vsbl']; 89 | usrFrm.picture_png := Fields.Values['bild']; 90 | myPara.VSession := Fields.Values['sesn']; 91 | 92 | // check session 93 | mypara.sip:= TheRequest.RemoteAddress; 94 | if NOT isSessionValid( mypara ) then 95 | begin 96 | Render(err_page, [myPara.lastError]); 97 | exit; 98 | end; 99 | usrFrm.iduser := inttostr( myPara.userID ); 100 | 101 | // no navi bars 102 | mypara.sCmd := '0'; 103 | // preset entry fault text 104 | sRet := accntErr; 105 | 106 | // translate input 107 | if usrFrm.isVisible = 'on' then 108 | usrFrm.isVisible := 'True' 109 | else 110 | usrFrm.isVisible := 'False'; 111 | 112 | // punish code injection 113 | usrFrm.Name := SecuredStr( usrFrm.Name ); 114 | usrFrm.pwd := SecuredStr( usrFrm.pwd ); 115 | usrFrm.MailAdress := SecuredStr( usrFrm.MailAdress ); 116 | if (usrFrm.Name = '') or (usrFrm.pwd ='') or (usrFrm.MailAdress = '') then 117 | begin 118 | sRet := sUpdate (sRet, '%%1', 'SQL Zeichen nicht erlaubt.'); 119 | sRet := sUpdate (sRet, '%%2', 'Aktion abgebrochen !'); 120 | Render('bbs_myacc.html', [make_Header_Accnt(mypara), sRet, make_Footer( conn, mypara ) ]); 121 | exit; 122 | end; 123 | 124 | // validate input 125 | if length( usrFrm.pwd ) < 6 then 126 | begin 127 | sRet := sUpdate (sRet, '%%1', 'Ihr Passwort muss mindesten 6 Zeichen lang sein.'); 128 | sRet := sUpdate (sRet, '%%2', 'Bitte korrigieren ..'); 129 | Render('bbs_myacc.html', [make_Header_Accnt(mypara), sRet, make_Footer( conn, mypara ) ]); 130 | exit; 131 | end; 132 | 133 | if usrFrm.pwd <> vPWD2 then 134 | begin 135 | sRet := sUpdate (sRet, '%%1', 'Passwort und Passwortbestätigung sind ungleich.'); 136 | sRet := sUpdate (sRet, '%%2', 'Bitte korrigieren ..'); 137 | Render('bbs_myacc.html', [make_Header_Accnt(mypara), sRet, make_Footer( conn, mypara ) ]); 138 | exit; 139 | end; 140 | 141 | // check input Image 142 | if usrFrm.picture_png <> '' then 143 | begin 144 | // check file type 145 | if UpperCase(RightStr(usrFrm.picture_png,3))<> 'PNG' then 146 | begin 147 | sRet := sUpdate (sRet, '%%1', 'Die Datei ' + usrFrm.picture_png + '

    ist keine PNG Datei.'); 148 | sRet := sUpdate (sRet, '%%2', 'Bitte ändern.'); 149 | Render('bbs_myacc.html', [make_Header_Accnt(mypara), sRet, make_Footer( conn, mypara ) ]); 150 | exit; 151 | end; 152 | 153 | VFormItem := Files[0]; 154 | // wait until file exists 155 | while not fileexists( BrookSettings.DirectoryForUploads + 156 | '\' + usrFrm.picture_png) do begin 157 | sleep(1000); 158 | // todo : add timeout 159 | end; 160 | // copy image from filesystem to string 161 | Stream := TMemoryStream.Create; 162 | stream.LoadFromFile( BrookSettings.DirectoryForUploads + 163 | '\' + usrFrm.picture_png ); 164 | stream.position := 0; 165 | // limit png size to db field type mediumtext max 166 | if stream.size > 124000 then 167 | begin 168 | stream.free; 169 | sRet := sUpdate (sRet, '%%1', 'Die Datei ' + usrFrm.picture_png + '

    ist zu groß. Maximum sind 124 kBytes.'); 170 | sRet := sUpdate (sRet, '%%2', 'Bitte ändern.'); 171 | Render('bbs_myacc.html', [make_Header_Accnt(mypara), sRet, make_Footer( conn, mypara ) ]); 172 | exit; 173 | end; 174 | // set picture_png to hexStr Format 175 | usrFrm.picture_png := ''; 176 | for i:= 1 to stream.size do 177 | usrFrm.picture_png += IntToHex(stream.ReadByte,2); 178 | stream.free; 179 | end; 180 | 181 | // read user 182 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + usrFrm.iduser, usrFrm1 ); 183 | usrFrm1.Name := usrFrm.Name ; 184 | usrFrm1.MailAdress := usrFrm.MailAdress; 185 | usrFrm1.pwd := usrFrm.pwd ; 186 | usrFrm1.isVisible := usrFrm.isVisible; 187 | usrFrm1.picture_png := usrFrm.picture_png; 188 | 189 | // sql update 190 | myPara.lastError := updUser( BrookFCLFCGIBroker.conn, usrFrm1 ); 191 | if myPara.lastError <> '' then 192 | begin 193 | Render(err_page, [myPara.lastError]); 194 | exit; 195 | end; 196 | 197 | redirect ('./myacc?sesn=' + myPara.VSession, 302); 198 | 199 | end; 200 | 201 | 202 | initialization 203 | TMyAccnt.Register('myacc'); 204 | 205 | end. 206 | 207 | -------------------------------------------------------------------------------- /newpost.pas: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // file : newpost.pas 3 | // created : 01.03.14 4 | // called via: 'cgi1/newpst?sesn=xxx&ID=1&Tpc=1' 5 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 6 | unit newPost; 7 | 8 | {$mode objfpc}{$H+} 9 | 10 | interface 11 | 12 | uses 13 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 14 | FmtBCD, sqldb, DateUtils, mapping, blowcryp, menu; 15 | 16 | type 17 | TNewPost = class(TBrookAction) 18 | public 19 | procedure Get; override; 20 | procedure Post; override; 21 | end; 22 | 23 | implementation 24 | 25 | 26 | procedure TNewPost.Get; 27 | VAR 28 | sBody, sFooter, sMenu, sTopic, sInfo : string; 29 | memFrm : ForInfType ; 30 | memTpc : TopInfType ; 31 | PstFrm : PstInfType ; 32 | usrFrm1: usrInfType ; 33 | usrFrm2: usrInfType ; 34 | myPara : ParaType; 35 | 36 | begin 37 | 38 | // check paras 39 | myPara.VSession := Params.Values['sesn']; 40 | memTpc.forum_id := Params.Values['Tpc']; 41 | memTpc.id := Params.Values['ID']; 42 | sMenu := Params.Values['B1']; 43 | sMenu += Params.Values['B2']; // form submits B1 or B2 44 | if memTpc.forum_id = '' then 45 | begin 46 | Render(err_page, ['Forum ID fehlt.']); 47 | exit; 48 | end; 49 | 50 | if memTpc.id = '' then 51 | begin 52 | Render(err_page, ['Topic ID fehlt.']); 53 | exit; 54 | end; 55 | mypara.sip:= TheRequest.RemoteAddress; 56 | if NOT isSessionValid( mypara ) then 57 | begin 58 | Render(err_page, [myPara.lastError]); 59 | exit; 60 | end; 61 | 62 | PstFrm.user_id := inttostr( myPara.userID ); 63 | PstFrm.post_time:= FormatDateTime('yyyy-mm-dd hh:nn:ss', now) ; 64 | 65 | // read forum info 66 | ReadForum( BrookFCLFCGIBroker.conn, 'where id=' + memTpc.forum_id, memFrm ); 67 | // read topic info 68 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 69 | // read user infos 70 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + PstFrm.user_id, usrFrm1 ); 71 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + memTpc.poster, usrFrm2 ); 72 | // set menu 73 | sFooter:= 'ha'; 74 | sMenu := '
  • TeamBBS Forum
  • ' + 75 | '
  • Forum: %%3
  • ' + 76 | '
  • Thema: %%4
  • ' + 77 | '
  • Abmelden
  • '; 78 | sMenu := sUpdate ( sMenu, '%%0', myPara.VSession ); 79 | sMenu := sUpdate ( sMenu, '%%1', memTpc.forum_id ); 80 | sMenu := sUpdate ( sMenu, '%%2', memTpc.id ); 81 | sMenu := sUpdate ( sMenu, '%%3', memFrm.fName ); 82 | sMenu := sUpdate ( sMenu, '%%4', memTpc.title ); 83 | 84 | // render topic 85 | sBody := '
    ' ; 86 | sTopic := '' + 87 | '' + 89 | '' + 90 | '
    ' + 88 | '%%7Erstellt von: %%2 am: %%3 - Letzter Aufruf von: %%4 am: %%5
    ' + 91 | '' + 92 | '
    ' + 93 | '
    ' ; 94 | 95 | sTopic := sUpdate( sTopic, '%%1', showUsrImage(usrFrm2) ); 96 | sTopic := sUpdate( sTopic, '%%2', memTpc.poster_name ); 97 | sTopic := sUpdate( sTopic, '%%3', memTpc.ctime ); 98 | sTopic := sUpdate( sTopic, '%%4', memTpc.last_poster_name ); 99 | sTopic := sUpdate( sTopic, '%%5', memTpc.last_post_time ); 100 | sTopic := sUpdate( sTopic, '%%6', memTpc.topic_text ); 101 | sTopic := sUpdate( sTopic, '%%7', showUsrInfo(usrFrm2) ); 102 | 103 | sBody += sTopic + 104 | '

    ' + 105 | '
    '; 106 | sTopic := '' + 107 | '' + 108 | '' + 109 | '' + 110 | '' + 111 | '' + 115 | '
    Neue Antwort von: %%1 am: %%2%%A
    ' + 116 | '' + 117 | '' + 118 | '' + 119 | '' + 120 | '
    ' ; 121 | 122 | 123 | sTopic := sUpdate( sTopic, '%%1', usrFrm1.Name ); 124 | sTopic := sUpdate( sTopic, '%%2', PstFrm.post_time ); 125 | sTopic := sUpdate( sTopic, '%%6', showUsrImage(usrFrm1) ); 126 | sTopic := sUpdate( sTopic, '%%7', memTpc.id ); 127 | sTopic := sUpdate( sTopic, '%%8', myPara.VSession ); 128 | sTopic := sUpdate( sTopic, '%%9', memTpc.forum_id ); 129 | sTopic := sUpdate( sTopic, '%%A', showUsrInfo(usrFrm1) ); 130 | sBody += sTopic + '
    '; 131 | sBody += '

    '; 132 | 133 | 134 | // display topic & posts 135 | Render('bbs_thread.html', [sMenu, sBody, sFooter] ); 136 | 137 | end; 138 | 139 | 140 | procedure TNewPost.Post; 141 | VAR 142 | I : Integer; 143 | sTmp : string; 144 | myPara : paraType; 145 | memFrm : ForInfType ; 146 | memTpc : TopInfType ; 147 | PstFrm : PstInfType ; 148 | usrFrm1: usrInfType ; 149 | badLst1: TStringList; 150 | badLst2: TStringList; 151 | myJob : JobType; 152 | 153 | begin 154 | 155 | mypara.sip := TheRequest.RemoteAddress; 156 | myPara.VSession := Fields.Values['sesn']; 157 | memTpc.id := Fields.Values['ID']; 158 | memTpc.forum_id := Fields.Values['Tpc']; 159 | PstFrm.post_text := Fields.Values['S2']; 160 | if NOT isSessionValid( mypara ) then 161 | begin 162 | Render(err_page, [myPara.lastError]); 163 | exit; 164 | end; 165 | 166 | PstFrm.user_id := IntToStr ( myPara.userID ); 167 | PstFrm.poster_ip := mypara.sip; 168 | 169 | 170 | // read forum, topic, user 171 | ReadForum ( BrookFCLFCGIBroker.conn, 'where id=' + memTpc.forum_id, memFrm ); 172 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 173 | ReadUsr ( BrookFCLFCGIBroker.conn, 'where iduser=' + PstFrm.user_id, usrFrm1 ); 174 | 175 | // cut off bad words 176 | /// german 177 | sTmp := GetContent( BrookFCLFCGIBroker.conn, 'bad_de' ); 178 | if sTmp <> 'none' then 179 | begin 180 | badLst1 := TStringList.Create; 181 | badLst1.TextLineBreakStyle := tlbsCRLF; 182 | badLst1.Text := sTmp; 183 | for I:=0 to badLst1.Count-1 do 184 | begin 185 | PstFrm.post_text:= StringReplace(PstFrm.post_text, TRIM(badLst1[i]), 186 | '/ups/', [rfReplaceAll, rfIgnoreCase]) ; 187 | end; 188 | badLst1.Free; 189 | end; 190 | 191 | 192 | /// english 193 | sTmp := GetContent( BrookFCLFCGIBroker.conn, 'bad_en' ); 194 | if sTmp <> 'none' then 195 | begin 196 | badLst2 := TStringList.Create; 197 | badLst2.TextLineBreakStyle := tlbsCRLF; 198 | badLst2.Text := sTmp; 199 | for I:=0 to badLst2.Count-1 do 200 | begin 201 | PstFrm.post_text:= StringReplace(PstFrm.post_text, TRIM(badLst2[i]), 202 | '/ups/', [rfReplaceAll, rfIgnoreCase]) ; 203 | end; 204 | badLst2.Free; 205 | end; 206 | 207 | 208 | // append posts 209 | PstFrm.topic_id := memTpc.id ; 210 | PstFrm.forum_id := memTpc.forum_id; 211 | PstFrm.post_subject := memTpc.title; 212 | PstFrm.post_alpha := LeftStr( StripHTML( PstFrm.post_text) , 255 ); 213 | PstFrm.post_size := IntToStr( Length ( PstFrm.post_text) ); 214 | myPara.lastError := posts_insert( BrookFCLFCGIBroker.conn, PstFrm ); 215 | if myPara.lastError <> '' then 216 | begin 217 | Render(err_page, [myPara.lastError]); 218 | exit; 219 | end; 220 | 221 | // update topic 222 | memTpc.views := sPlus( memTpc.views ); 223 | memTpc.replies := sPlus( memTpc.replies ); 224 | memTpc.replies_real := sPlus( memTpc.replies_real ); 225 | memTpc.last_poster_id := PstFrm.user_id ; 226 | memTpc.last_poster_name := usrFrm1.Name; 227 | memTpc.last_post_subject:= PstFrm.Post_subject; 228 | memTpc.last_post_time := DateTimeToStr (now) ; 229 | memTpc.last_view_time := memTpc.last_post_time ; 230 | 231 | myPara.lastError := Topic_Update( BrookFCLFCGIBroker.conn, memTpc ); 232 | if myPara.lastError <> '' then 233 | begin 234 | Render(err_page, [myPara.lastError]); 235 | exit; 236 | end; 237 | 238 | // update forum 239 | memFrm.topics := sPlus( memFrm.topics ); 240 | memFrm.posts := sPlus( memFrm.posts ); 241 | memFrm.last_poster_id := usrFrm1.iduser ; 242 | memFrm.last_poster_name := usrFrm1.Name; 243 | memFrm.last_post_subject := memTpc.title; 244 | myPara.lastError := Upd_Forum( BrookFCLFCGIBroker.conn, memFrm ); 245 | if myPara.lastError <> '' then 246 | begin 247 | Render(err_page, [myPara.lastError]); 248 | exit; 249 | end; 250 | 251 | // start job info 252 | myJob.inquirer := conn.UserName; 253 | myJob.inqIP := PstFrm.poster_ip; 254 | myJob.Intervall := '0'; 255 | 256 | // insert job 'badwords' 257 | if POS( '/ups/', PstFrm.post_text ) > 0 then 258 | begin 259 | myJob.iduser := PstFrm.user_id ; 260 | myJob.Action := 'badwords'; 261 | myJob.Context := '|' + memTpc.id + '|' ; 262 | job_insert ( BrookFCLFCGIBroker.conn, myJob ); 263 | end; 264 | 265 | // Insert job 'postinfo' 266 | myJob.iduser := memTpc.poster; 267 | myJob.Action := 'postinfo'; 268 | myJob.Context := '|' + usrfrm1.iduser + '|' + memTpc.id + '|'; 269 | job_insert ( BrookFCLFCGIBroker.conn, myJob ); 270 | 271 | 272 | redirect ('topic?ID=' + PstFrm.forum_id + '&Tpc=' + PstFrm.topic_id + '&sesn=' + myPara.VSession , 302); 273 | 274 | 275 | end; 276 | 277 | initialization 278 | TNewPost.Register('newpst'); 279 | 280 | end. 281 | 282 | -------------------------------------------------------------------------------- /news.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 07.05.14 5 | // file : news.pas 6 | // list posts & topics sind last login 7 | 8 | unit news; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses 15 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 16 | FmtBCD, sqldb, blowcryp, mapping, menu; 17 | 18 | type 19 | Tnews = class(TBrookAction) 20 | public 21 | procedure Get; override; 22 | end; 23 | 24 | implementation 25 | 26 | procedure Tnews.Get; 27 | var 28 | i : integer; 29 | sRslt, body, sDate : String; 30 | mySessn: sessInfType; 31 | myPara : paraType; 32 | query : TSQLQuery; 33 | 34 | begin 35 | 36 | // read paras 37 | myPara.VSession := Params.Values['sesn']; 38 | 39 | // check session timeout 40 | mypara.sip:= TheRequest.RemoteAddress; 41 | if NOT isSessionValid( mypara ) then 42 | begin 43 | Render(err_page, ['session timeout ' + myPara.lastError + myPara.VSession + inttostr(i) ]); 44 | exit; 45 | end; 46 | 47 | // get session info 48 | paraTypeInit('news?', myPara ); // init mypara 49 | mypara.sCmd := '1'; // '1' full menus 50 | mySessn.id := mypara.VSession; // read session rec 51 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 52 | sesn_copy_para( mySessn, myPara ); 53 | 54 | 55 | // build query 56 | sRslt := 'SELECT * from find where post_time > "' + 57 | FormatDateTime(sqlDate, StrToDateTime(mySessn.lastlogin)) + '" '; 58 | 59 | // set display order 60 | case myPara.v_order of 61 | '1' : sRslt += ' ORDER BY post_time'; 62 | '2' : sRslt += ' ORDER BY iduser'; 63 | '3' : sRslt += ' ORDER BY forum_id'; 64 | end; 65 | 66 | // set limit ( start,stop ) 67 | sRslt += ' limit ' + 68 | IntToStr( StrToInt( myPara.v_page ) * PageItems ) + ',' + 69 | IntToStr( StrToInt( myPara.v_page ) * PageItems + PageItems+1 ); 70 | 71 | ////////////////////// 72 | // main query 73 | query := TSQLQuery.Create(nil); 74 | query.DataBase := BrookFCLFCGIBroker.conn; 75 | query.SQL.Text := sRslt; 76 | query.Open; 77 | 78 | i := 0; 79 | body := ''; 80 | while not query.EOF do 81 | begin 82 | sRslt := sUpdate(findrslt,'%%1','' + 84 | query.FieldByName('fname').AsString + '' ); 85 | sRslt := sUpdate( sRslt, '%%2','' + 88 | query.FieldByName('title').AsString + '' ); 89 | sRslt := sUpdate( sRslt, '%%3',StripHTML( query.FieldByName('post_text').AsString) ); 90 | sRslt := sUpdate( sRslt, '%%4','' + 92 | query.FieldByName('Name').AsString + '' ); 93 | body += sRslt; 94 | i += 1; 95 | if i = PageItems then break; 96 | query.next; 97 | end; 98 | 99 | // Build last table line 100 | sRslt := sUpdate( newsinfo, '%%5', mySessn.lastlogin); 101 | body += sRslt; 102 | 103 | // set footer info 104 | myPara.v_eof := iif( query.EOF, '1', '0'); // eof flag 105 | 106 | // show page 107 | Render('bbs_news.html', [ make_header(mypara), // header 108 | body, // body 109 | make_footer( BrookFCLFCGIBroker.conn, mypara) ]); // footer 110 | // release mem 111 | query.active := False; 112 | query.Free; 113 | 114 | end; 115 | 116 | initialization 117 | Tnews.Register('news'); 118 | 119 | end. 120 | 121 | -------------------------------------------------------------------------------- /newthm.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 11.02.14 5 | // file : newThm.pas 6 | // modified : 12.03.14 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | // called via: 'cgi1/forum?ID=XXXX&sesn=XXXXXXXXXXXXXXX' 9 | 10 | unit newThm; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses 17 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 18 | FmtBCD, sqldb, blowcryp, mapping, menu; 19 | 20 | type 21 | TnewThm = class(TBrookAction) 22 | public 23 | procedure Get; override; 24 | procedure Post; override; 25 | end; 26 | 27 | implementation 28 | 29 | procedure TnewThm.Get; 30 | VAR 31 | memQry : ForInfType; 32 | memTpc : TopInfType; 33 | usrFrm1: usrInfType; 34 | myPara : ParaType; 35 | 36 | begin 37 | 38 | // check paras 39 | memTpc.forum_id := Params.Values['ID']; 40 | myPara.VSession := Params.Values['sesn']; 41 | mypara.sip:= TheRequest.RemoteAddress; 42 | if NOT isSessionValid( mypara ) then 43 | begin 44 | Render(err_page, [myPara.lastError]); 45 | exit; 46 | end; 47 | 48 | if memTpc.forum_id = '' then 49 | begin 50 | Render(err_page, ['Forum ID fehlt.']); 51 | exit; 52 | end; 53 | 54 | // copy from db to record 55 | ReadForum( BrookFCLFCGIBroker.conn, 'where id=' + memTpc.forum_id, memQry ); 56 | ReadUsr ( BrookFCLFCGIBroker.conn, 'where iduser=' + IntToStr(myPara.userID), usrFrm1 ); 57 | 58 | // start render 59 | myPara.Text1 := 'newthm?' ; // saved in session.forward_for 60 | myPara.sID := memTpc.forum_id ; 61 | myPara.sTopic:= memQry.fName ; 62 | 63 | Render('bbs_newthm.html', [ make_Header_newThm(mypara), 64 | showUsrImage(usrFrm1), // Usr Image 65 | showUsrInfo(usrFrm1), // Usr Info 66 | usrFrm1.Name, // Column 2 Usr Name 67 | memQry.fName, // Column 2 Forum Name 68 | mypara.VSession, 69 | memTpc.forum_id, 70 | make_Footer( BrookFCLFCGIBroker.conn, mypara ) ]); 71 | 72 | 73 | end; 74 | 75 | 76 | procedure TnewThm.Post; 77 | VAR 78 | memFrm : ForInfType; 79 | memTpc : TopInfType; 80 | usrFrm1: usrInfType; 81 | sNotify: string; 82 | myPara : ParaType; 83 | 84 | begin 85 | 86 | // read para 87 | sNotify := Fields.Values['vsbl']; 88 | myPara.VSession := Fields.Values['sesn']; 89 | mypara.sCmd := Fields.Values['B1']; 90 | mypara.sCmd += Fields.Values['B2']; // form posts B1 or B2 91 | memTpc.forum_id := Fields.Values['forum']; 92 | memTpc.title := Fields.Values['tpc_name']; 93 | memTpc.topic_text:= Fields.Values['S1']; 94 | // check session 95 | mypara.sip:= TheRequest.RemoteAddress; 96 | if NOT isSessionValid( mypara ) then 97 | begin 98 | Render(err_page, [myPara.lastError]); 99 | exit; 100 | end; 101 | 102 | // check submit button 103 | if mypara.sCmd <> 'Senden' then redirect ('./main?sesn=' + mypara.VSession, 302); 104 | 105 | usrFrm1.iduser := inttostr( mypara.userID ); 106 | memTpc.poster := usrFrm1.iduser; 107 | 108 | 109 | ReadForum( BrookFCLFCGIBroker.conn, 'where id=' + memTpc.forum_id, memFrm ); 110 | ReadUsr ( BrookFCLFCGIBroker.conn, 'where iduser=' + usrFrm1.iduser, usrFrm1 ); 111 | memTpc.poster_name := usrFrm1.Name; 112 | 113 | // insert new topic 114 | myPara.lastError := topic_insert( BrookFCLFCGIBroker.conn, memTpc ); 115 | if myPara.lastError <> '' then 116 | begin 117 | Render(err_page, [myPara.lastError]); 118 | exit; 119 | end; 120 | 121 | // update forum 122 | memFrm.topics := sPlus( memFrm.topics ); 123 | memFrm.posts := sPlus( memFrm.posts ); 124 | memFrm.last_poster_id := usrFrm1.iduser ; 125 | memFrm.last_poster_name := usrFrm1.Name; 126 | memFrm.last_post_subject:= memTpc.title; 127 | myPara.lastError := Upd_Forum( BrookFCLFCGIBroker.conn, memFrm ); 128 | if myPara.lastError <> '' then 129 | begin 130 | Render(err_page, [myPara.lastError]); 131 | exit; 132 | end; 133 | 134 | redirect ('./forum?ID=' + memTpc.forum_id + '&sesn=' + myPara.VSession, 302); 135 | 136 | end; 137 | 138 | initialization 139 | TnewThm.Register('newthm'); 140 | 141 | end. 142 | 143 | -------------------------------------------------------------------------------- /posts.pas: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // file : posts.pas 4 | // created : 02.03.14 5 | // called via: 'cgi1/topic?ID=1;Tpc=1' 6 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 7 | 8 | unit posts; 9 | {$mode objfpc}{$H+} 10 | 11 | interface 12 | 13 | uses 14 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 15 | FmtBCD, sqldb, DateUtils, mapping, blowcryp, menu; 16 | 17 | type 18 | TPosts = class(TBrookAction) 19 | public 20 | procedure Get; override; 21 | end; 22 | 23 | implementation 24 | 25 | 26 | 27 | procedure TPosts.Get; 28 | var 29 | I : Integer; 30 | sMenu, sBody, sTopic, sTmp, sPage : string; 31 | memFrm : ForInfType; 32 | memTpc : TopInfType; 33 | PstFrm : PstInfType; 34 | usrFrm1: usrInfType; 35 | usrFrm2: usrInfType; 36 | mySessn: sessInfType; 37 | myPara : paraType; 38 | query : TSQLQuery; 39 | 40 | begin 41 | 42 | // check paras 43 | mypara.sip := TheRequest.RemoteAddress; 44 | myPara.VSession := Params.Values['sesn']; 45 | memTpc.forum_id := Params.Values['ID']; 46 | memTpc.id := Params.Values['Tpc']; 47 | sPage := Params.Values['page']; // resest vpage para 48 | 49 | if memTpc.forum_id = '' then 50 | begin 51 | Render(err_page, ['Forum ID fehlt: ' + memTpc.forum_id ]); 52 | exit; 53 | end; 54 | 55 | if memTpc.id = '' then 56 | begin 57 | Render(err_page, ['Topic ID fehlt: ' + memTpc.id ]); 58 | exit; 59 | end; 60 | 61 | 62 | if NOT isSessionValid( mypara ) then 63 | begin 64 | Render(err_page, [myPara.lastError]); 65 | exit; 66 | end; 67 | 68 | // read forum info 69 | ReadForum( BrookFCLFCGIBroker.conn, 'where id=' + memTpc.forum_id, memFrm ); 70 | // read session user 71 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + inttostr(mypara.userID), usrFrm1 ); 72 | // read topic info 73 | Topic_Read( BrookFCLFCGIBroker.conn, memTpc ); 74 | // refresh topic access infos 75 | memTpc.views := sPlus( memTpc.Views ); 76 | memTpc.last_view_time := DateTimeToStr( now()); 77 | memTpc.last_poster_name := usrFrm1.Name; 78 | Topic_Update( BrookFCLFCGIBroker.conn, memTpc ); 79 | // read topic user 80 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + memTpc.poster, usrFrm1 ); 81 | 82 | // render topic 83 | sTopic := '
    ' + 84 | '' + 85 | '' + 87 | '' + 88 | '
    ' + 86 | '%%AErstellt von: %%2 am: %%3 - Letzter Aufruf von: %%4 am: %%5
    ' + 89 | '' + 90 | '' + 97 | '
    ' + 98 | '
    ' + 99 | '' + 100 | '' + 101 | '' + 102 | '' + 103 | '
    '; 104 | 105 | /// show topic edit button if current user = topic creator 106 | if inttostr( mypara.userID ) = memTpc.poster then 107 | sTopic += '
    ' + 108 | '' + 109 | '' + 110 | '' + 111 | '' + 112 | '
    ' ; 113 | 114 | sTopic += '

    '; 115 | sTopic := sUpdate( sTopic, '%%1', showUsrImage(usrFrm1) ); 116 | sTopic := sUpdate( sTopic, '%%2', memTpc.poster_name ); 117 | sTopic := sUpdate( sTopic, '%%3', memTpc.ctime ); 118 | sTopic := sUpdate( sTopic, '%%4', memTpc.last_poster_name ); 119 | sTopic := sUpdate( sTopic, '%%5', memTpc.last_view_time ); 120 | sTopic := sUpdate( sTopic, '%%6', memTpc.topic_text ); 121 | sTopic := sUpdate( sTopic, '%%7', memTpc.id ); 122 | sTopic := sUpdate( sTopic, '%%8', mypara.VSession ); 123 | sTopic := sUpdate( sTopic, '%%9', memTpc.forum_id ); 124 | sTopic := sUpdate( sTopic, '%%A', showUsrInfo(usrFrm1) ); 125 | sBody := sTopic; 126 | 127 | // read sesion info to set display order 128 | mySessn.id := mypara.VSession; 129 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 130 | // reset page count if spage=0 131 | if spage = '0' then 132 | begin 133 | mySessn.v_page:='0'; 134 | sesn_update( BrookFCLFCGIBroker.conn, mySessn ); 135 | end; 136 | 137 | case mySessn.v_order of 138 | '0' : sTmp := '' ; 139 | '1' : sTmp := ' ORDER BY post_time'; 140 | '2' : sTmp := ' ORDER BY post_size'; 141 | '3' : sTmp := ' ORDER BY post_alpha'; 142 | end; 143 | 144 | 145 | // set session info 146 | mypara.sCmd := '1'; // '1' full menus 147 | myPara.sID := memTpc.forum_id; 148 | myPara.sTopic := memFrm.fName ; 149 | myPara.sPst := memTpc.id; 150 | myPara.v_page := mySessn.v_page; 151 | myPara.Text1 := 'topic?ID=' + memTpc.forum_id + '&Tpc=' + memTpc.id; // saved in session.forward_for 152 | myPara.text2 := memTpc.title; 153 | 154 | // read posts info 155 | query := TSQLQuery.Create(nil); 156 | query.DataBase := BrookFCLFCGIBroker.conn; 157 | query.SQL.Text := 'SELECT * FROM posts where topic_id=' + memTpc.id + 158 | sTmp + // order by 159 | ' limit ' + // limit start,stop 160 | IntToStr( StrToInt( mySessn.v_page ) * PageItems ) 161 | + ',' + IntToStr( StrToInt( mySessn.v_page ) * PageItems + PageItems+1 ); 162 | query.Open; 163 | if query.EOF then 164 | begin 165 | // set menu info for topic w/o posts 166 | myPara.sID := memTpc.forum_id; 167 | myPara.sTopic := memFrm.fName ; 168 | myPara.sPst := memTpc.id; 169 | myPara.text2 := memTpc.title; 170 | sMenu := make_Header_Posts( myPara ); 171 | mypara.sCmd := '0'; // switch off navi bars in footer 172 | Render('bbs_thread.html', [sMenu, sBody, make_Footer( BrookFCLFCGIBroker.conn, mypara )] ); 173 | // free mem 174 | query.active := false; 175 | query.free; 176 | exit; 177 | end; 178 | 179 | 180 | 181 | // render posted replies 182 | i := 0; 183 | sBody := sBody + '
    '; 184 | while not query.EOF do 185 | begin 186 | // read 187 | cpyPostInfo( Query, PstFrm ); 188 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + PstFrm.user_id, usrFrm1 ); 189 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + PstFrm.post_edit_user, usrFrm2 ); 190 | 191 | // build display string 192 | sTopic := '' + 193 | '' + 194 | '' + 195 | '
    Antwort von: %%1 am: %%2 - Letzter Aufruf von: %%3 am: %%4%%A
    ' + 196 | '
    '; 197 | 198 | // show post edit buttons if current user = post creator 199 | if inttostr( mypara.userID ) = PstFrm.user_id then 200 | sTopic += '
    ' + 201 | '' + 202 | '' + 203 | '' + 204 | '' + 205 | '' + 206 | '
    ' ; 207 | 208 | sTopic += '
    ' ; 209 | sTopic := sUpdate( sTopic, '%%1', usrFrm1.Name ); 210 | sTopic := sUpdate( sTopic, '%%2', PstFrm.post_time ); 211 | sTopic := sUpdate( sTopic, '%%3', usrFrm2.Name ); 212 | sTopic := sUpdate( sTopic, '%%4', PstFrm.post_edit_time ); 213 | sTopic := sUpdate( sTopic, '%%5', PstFrm.post_text ); 214 | sTopic := sUpdate( sTopic, '%%6', showUsrImage(usrFrm1) ); 215 | sTopic := sUpdate( sTopic, '%%A', showUsrInfo(usrFrm1) ); 216 | 217 | // set post edit buttons links 218 | if inttostr( mypara.userID ) = PstFrm.user_id then 219 | begin 220 | sTopic := sUpdate( sTopic, '%%7', PstFrm.id ); 221 | sTopic := sUpdate( sTopic, '%%8', mypara.VSession ); 222 | sTopic := sUpdate( sTopic, '%%9', PstFrm.user_id ); 223 | end; 224 | sBody += sTopic + '
    '; 225 | i += 1; 226 | if i = PageItems then break; 227 | query.next; 228 | end; 229 | sBody += '

    '; 230 | 231 | mypara.V_rec := query.FieldByName('id').asString; 232 | if query.EOF then 233 | mypara.v_eof := '1' 234 | ELSE 235 | mypara.v_eof := '0'; 236 | 237 | 238 | // set menu 239 | mypara.sCmd := '1'; // '1' full menus 240 | myPara.sID := memTpc.forum_id; 241 | myPara.sTopic := memFrm.fName ; 242 | myPara.sPst := memTpc.id; 243 | myPara.Text1 := 'topic?ID=' + memTpc.forum_id + '&Tpc=' + memTpc.id; // saved in session.forward_for 244 | myPara.text2 := memTpc.title; 245 | 246 | // display topic & posts 247 | Render('bbs_thread.html', [make_Header_Posts( myPara ), 248 | sBody, 249 | make_Footer( BrookFCLFCGIBroker.conn, mypara )] ); 250 | 251 | // release mem 252 | query.active := false; 253 | query.free; 254 | 255 | end; 256 | 257 | 258 | initialization 259 | TPosts.Register('topic'); 260 | 261 | end. 262 | 263 | -------------------------------------------------------------------------------- /registerusr.pas: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////// 2 | // file : RegisterUsr.pas 3 | // called as 'cgi1/account' 4 | // modified : 03.03.14 5 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 6 | // function 7 | // check fields, prompt on non unique vName 8 | // add entry to eaihot table for confirmation mail 9 | // eaihot records are processed by eaihot daemon. 10 | // new & approve account 'cgi1/approve' 11 | 12 | unit RegisterUsr; 13 | 14 | {$mode objfpc}{$H+} 15 | 16 | interface 17 | 18 | uses 19 | BrookAction, BrookFCLFCGIBroker, BrookConsts, SysUtils, Variants, 20 | FmtBCD, sqldb, mapping, blowcryp, menu; 21 | 22 | 23 | type 24 | TAccount = class(TBrookAction) 25 | public 26 | procedure Get; override; 27 | end; 28 | 29 | TApprove = class(TBrookAction) 30 | public 31 | procedure get; override; 32 | end; 33 | 34 | implementation 35 | 36 | 37 | ///////////////////////////////////////////////////////////////// 38 | // Confirm Mail Handler: 39 | // .. confirm request by klicking link below: 40 | // http://localhost/cgi-bin/cgi1/approve?ID=38000026016823 41 | procedure TApprove.Get; 42 | var 43 | sID, sRet : String; 44 | myPara : ParaType; 45 | usrFrm : usrInfType; 46 | 47 | 48 | begin 49 | // parse parameters 50 | myPara.VSession := Params.Values['ID']; 51 | // no navi bars 52 | mypara.sCmd := '0'; 53 | sRet := '


    Hallo,
    die Aktivierung des Accounts muss innerhalb 24 Stunden
    ' + 54 | 'erfolgen. Eine spätere Aktivierung ist nicht möglich
    Bitte erstellen Sie einen neuen Account.
    ' + 55 | '
    OK
    '; 56 | 57 | 58 | // parse session string 59 | myPara.sIP := TheRequest.RemoteAddress; 60 | if decodeSessionID( myPara ) > 1440 then 61 | begin 62 | Render('bbs_accnt.html', [make_Header(mypara), sRet, make_Footer( conn, mypara )]); 63 | exit; 64 | end; 65 | 66 | 67 | // ReadUsr 68 | usrFrm.iduser := IntToStr(myPara.userID); 69 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + usrFrm.iduser, usrFrm ); 70 | if usrFrm.iduser = '' then 71 | begin 72 | Render('bbs_accnt.html', [make_Header(mypara), 73 | sRet, 74 | make_Footer( BrookFCLFCGIBroker.conn, mypara )]); 75 | exit; 76 | end; 77 | 78 | // update vars 79 | usrFrm.RegisterIP := myPara.sIP; 80 | usrFrm.RegisterTime := DateTimeToStr( now ) ; 81 | usrFrm.isChecked := 'True'; 82 | myPara.lastError := updUser(BrookFCLFCGIBroker.conn,usrFrm); 83 | if myPara.lastError <> '' then 84 | begin 85 | Render(err_page, [myPara.lastError]); 86 | exit; 87 | end; 88 | 89 | sRet := '

    Hallo ' + usrFrm.Name + ',
    Ihr Account ist aktiviert.
    Ihre Mail Adresse:
    ' + 90 | usrFrm.MailAdress + '
    OK
    '; 91 | 92 | Render('bbs_accnt.html', [make_Header(mypara), 93 | sRet, 94 | make_Footer( BrookFCLFCGIBroker.conn, mypara )]); 95 | 96 | end; 97 | 98 | procedure TAccount.Get; 99 | var 100 | i: integer; 101 | vPWD2, vagb, sRet : string; 102 | myPara : ParaType; 103 | usrFrm : usrInfType; 104 | myJob : JobType; 105 | 106 | begin 107 | 108 | // no navi bars 109 | mypara.sCmd := '0'; 110 | 111 | 112 | if Params.Count = 0 then 113 | begin 114 | sRet := '
    Benutzername
    ' + 115 | '
    ' + 116 | '
    eMail
    ' + 117 | '
    ' + 118 | '
    Passwort
    ' + 119 | '' + 120 | '
    Passwort bestätigen
    ' + 121 | '
    ' + 122 | 'Ich stimme den Nutzungsbedingungen zu

    ' + 123 | '
    '; 124 | Render('bbs_accnt.html', [make_Header(mypara), sRet, make_Footer( conn, mypara )]); 125 | exit; 126 | end; 127 | 128 | // read paras 129 | vPWD2:= Params.Values['password_confirm']; 130 | vagb := Params.Values['agb']; 131 | 132 | mypara.VSession := Params.Values['sesn']; 133 | usrFrm.Name := Params.Values['usr_name']; 134 | usrFrm.MailAdress := Params.Values['emailsignup']; 135 | usrFrm.pwd := Params.Values['password']; 136 | // punish code injection 137 | usrFrm.Name := SecuredStr( usrFrm.Name ); 138 | usrFrm.pwd := SecuredStr( usrFrm.pwd ); 139 | usrFrm.MailAdress := SecuredStr( usrFrm.MailAdress ); 140 | 141 | // preset entry fault text 142 | sRet := accntErr; 143 | 144 | // check paras 145 | if (usrFrm.Name = '') or (usrFrm.pwd ='') or (usrFrm.MailAdress = '') then 146 | begin 147 | sRet := sUpdate (sRet, '%%1', 'SQL Zeichen nicht erlaubt.'); 148 | sRet := sUpdate (sRet, '%%2', 'Aktion abgebrochen !'); 149 | Render('bbs_accnt.html', [make_Header(mypara), sRet, make_Footer( conn, mypara ) ]); 150 | exit; 151 | end; 152 | 153 | // validate input 154 | if length( usrFrm.pwd ) < 6 then 155 | begin 156 | sRet := sUpdate (sRet, '%%1', 'Ihr Passwort muss mindesten 6 Zeichen lang sein.'); 157 | sRet := sUpdate (sRet, '%%2', 'Bitte korrigieren ..'); 158 | Render('bbs_accnt.html', [make_Header(mypara), sRet, make_Footer( conn, mypara ) ]); 159 | exit; 160 | end; 161 | 162 | if usrFrm.pwd <> vPWD2 then 163 | begin 164 | sRet := sUpdate (sRet, '%%1', 'Passwort und Passwortbestätigung sind ungleich.'); 165 | sRet := sUpdate (sRet, '%%2', 'Bitte korrigieren ..'); 166 | Render('bbs_accnt.html', [make_Header(mypara), sRet, make_Footer( conn, mypara) ]); 167 | exit; 168 | end; 169 | 170 | // check if user already exists 171 | ReadUsr ( conn, ' where name="' + TRIM(usrFrm.Name) + '"', usrFrm ); 172 | if usrFrm.iduser <> '' then 173 | begin 174 | sRet := sUpdate (sRet, '%%1', 'Der Benutzername: ' + usrFrm.Name + '
    ist leider schon vergeben.
    '); 175 | sRet := sUpdate (sRet, '%%2', 'Bitte geben Sie einen anderen Namen ein.'); 176 | Render('bbs_accnt.html', [make_Header(mypara), sRet, make_Footer( conn, mypara) ]); 177 | exit; 178 | end; 179 | 180 | // insert new user 181 | usrFrm.pwd := encrypt(usrFrm.pwd); 182 | usrFrm.RegisterIP := TheRequest.RemoteAddress; 183 | User_insert( BrookFCLFCGIBroker.conn, usrFrm ); 184 | 185 | // read again to get recid of new user 186 | ReadUsr ( BrookFCLFCGIBroker.conn, ' where name="' + TRIM(usrFrm.Name) + '"', usrFrm ); 187 | if usrFrm.iduser = '' then 188 | begin 189 | sRet := '

    Account Info:

    Verbindungsfehler.
    Bitte später versuchen..
    ' + 190 | '
    OK
    '; 191 | Render('bbs_accnt.html', [make_Header(mypara), 192 | sRet, 193 | make_Footer( BrookFCLFCGIBroker.conn, mypara) ]); 194 | exit; 195 | end; 196 | 197 | // Insert job 'regmail' 198 | myJob.inquirer := conn.UserName; 199 | myJob.inqIP := TheRequest.RemoteAddress; 200 | myJob.iduser := usrFrm.iduser; 201 | myJob.Action := 'regmail'; 202 | myJob.Intervall := '0'; 203 | myJob.Context := '|'; 204 | job_insert ( BrookFCLFCGIBroker.conn, myJob ); 205 | 206 | // render 207 | sRet := '

    Account Info:

    Account erstellt.
    Sie erhalten eine Mail
    mit einem Aktivierungslink
    an die Mail Adresse
    ' + 208 | usrFrm.MailAdress + '
    OK
    '; 209 | Render('bbs_accnt.html', [make_Header(mypara), 210 | sRet, 211 | make_Footer( conn, mypara) ]); 212 | 213 | end; 214 | 215 | 216 | 217 | initialization 218 | TAccount.Register('accnt'); 219 | TApprove.Register('approve'); 220 | 221 | end. 222 | 223 | -------------------------------------------------------------------------------- /upload.pas: -------------------------------------------------------------------------------- 1 | unit Upload; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | BrookAction, BrookConsts, BrookUtils, HTTPDefs, SysUtils; 9 | 10 | type 11 | TTest = class(TBrookAction) 12 | public 13 | procedure Get; override; 14 | procedure Post; override; 15 | end; 16 | 17 | const 18 | RESULT = 19 | 'All files:' + BR + LF + '%s' + BR + BR + LF + 20 | 'All files saved in:' + BR + LF + '%s'; 21 | 22 | implementation 23 | 24 | procedure TTest.Get; 25 | begin 26 | Write({$i head.inc}, [{$i form.inc}]); 27 | end; 28 | 29 | procedure TTest.Post; 30 | var 31 | I: Integer; 32 | VFiles, VSep: string; 33 | VFormItem: TUploadedFile; 34 | begin 35 | VFiles := ''; 36 | VSep := '||'; 37 | for I := 0 to Pred(Files.Count) do 38 | begin 39 | VFormItem := Files[I]; 40 | if VFormItem.FileName <> '' then 41 | VFiles += VFormItem.FileName + VSep; 42 | end; 43 | Write({$i head.inc}, 44 | [Format(RESULT, [VFiles, BrookSettings.DirectoryForUploads])]); 45 | end; 46 | 47 | initialization 48 | TTest.Register('upload'); 49 | 50 | end. 51 | 52 | -------------------------------------------------------------------------------- /upst.pas: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////// 2 | // project : bbs_fcgi 3 | // author : Ralph Berger 4 | // created : 10.03.14 5 | // file : upst.pas 6 | // show user posts for select or current user 7 | // modified : 24.04.2014 BF 2.6.4 -> BF 3.0.0 8 | 9 | unit upst; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses 16 | BrookAction, BrookFCLFCGIBroker, BrookConsts, Classes, SysUtils, Variants, 17 | FmtBCD, sqldb, blowcryp, mapping, menu; 18 | 19 | 20 | type 21 | TUpst = class(TBrookAction) 22 | public 23 | procedure Get; override; 24 | end; 25 | 26 | 27 | implementation 28 | 29 | 30 | procedure TUpst.Get; 31 | Var 32 | i,lastID: integer; 33 | sBody, sTmp : String; 34 | usrFrm1 : usrInfType; 35 | myPara : paraType; 36 | mySessn : sessInfType; 37 | query : TSQLQuery; 38 | 39 | 40 | begin 41 | 42 | // read paras 43 | myPara.VSession := Params.Values['sesn']; 44 | myPara.sID := Params.Values['ID']; 45 | // check session 46 | mypara.sip:= TheRequest.RemoteAddress; 47 | if NOT isSessionValid( mypara ) then 48 | begin 49 | Render(err_page, [myPara.lastError]); 50 | exit; 51 | end; 52 | 53 | // session callback target 54 | paraTypeInit('upst?ID=' + myPara.sID, myPara ); 55 | mypara.sCmd := '1'; // '1' full menus 56 | // read sesion info 57 | mySessn.id := mypara.VSession; 58 | sesn_Read( BrookFCLFCGIBroker.conn, mySessn ); 59 | sesn_copy_para( mySessn, myPara ); 60 | 61 | // set session info 62 | if myPara.sID = '' then myPara.sID := IntToStr( myPara.userID ); // show logon user postings 63 | mypara.sCmd := '1'; // '1' full menus 64 | 65 | // set display order 66 | case myPara.v_order of 67 | '0' : sTmp := '' ; 68 | '1' : sTmp := ' ORDER BY topics.forum_id'; 69 | '2' : sTmp := ' ORDER BY topics.topic_text'; 70 | '3' : sTmp := ' ORDER BY topics.ctime'; 71 | end; 72 | 73 | 74 | // read session user 75 | ReadUsr( BrookFCLFCGIBroker.conn, 'where iduser=' + mypara.sID, usrFrm1 ); 76 | sBody := sUpdate( usrTbl,'%%0', showUsrImage(usrFrm1) ); 77 | sBody := sUpdate( sBody, '%%1', count_usr_themes(BrookFCLFCGIBroker.conn, usrFrm1) ); 78 | sBody := sUpdate( sBody, '%%2', count_usr_posts(BrookFCLFCGIBroker.conn, usrFrm1) + showUsrInfo(usrFrm1) ); 79 | 80 | myPara.Text2 := usrFrm1.Name; 81 | 82 | // read forums and child posts 83 | query := TSQLQuery.Create(nil); 84 | query.DataBase := BrookFCLFCGIBroker.conn; 85 | query.SQL.Text := 'SELECT * FROM topics left join posts on ( topics.id = posts.forum_id ) ' + 86 | 'WHERE topics.poster =' + mypara.sID + ' OR posts.user_id =' + mypara.sID + 87 | sTmp + // set order 88 | ' limit ' + // limit start,stop 89 | IntToStr( StrToInt( mySessn.v_page ) * PageItems ) 90 | + ',' + IntToStr( StrToInt( mySessn.v_page ) * PageItems + PageItems+1 ); 91 | query.Open; 92 | 93 | i := 0; 94 | while not query.EOF do 95 | begin 96 | if query.FieldByName('forum_id').AsInteger <> lastID then 97 | begin 98 | sTmp := sUpdate( tpcTbl,'%%3', query.FieldByName('title').AsString ); 99 | sTmp := sUpdate( sTmp, '%%4', query.FieldByName('ctime').AsString ); 100 | sTmp := sUpdate( sTmp, '%%5', query.FieldByName('topic_text').AsString ); 101 | sBody += sTmp; 102 | end; 103 | 104 | if query.FieldByName('user_id').IsNull = false then 105 | begin 106 | sTmp := sUpdate( pstTbl,'%%6', query.FieldByName('post_time').AsString ); 107 | sTmp := sUpdate( sTmp, '%%7', query.FieldByName('post_text').AsString ); 108 | sBody += sTmp; 109 | end; 110 | 111 | 112 | lastID := query.FieldByName('id').AsInteger; 113 | i += 1; 114 | if i = PageItems then break; 115 | query.next; 116 | end; 117 | 118 | mypara.V_rec := IntToStr(lastID); // rec id 119 | myPara.v_eof := iif( query.EOF, '1', '0'); // eof flag 120 | 121 | // display 122 | Render('bbs_upst.html', [make_Header_UPosts( myPara ), 123 | sBody , 124 | make_Footer( BrookFCLFCGIBroker.conn, myPara ) ]); 125 | 126 | 127 | // release mem 128 | query.active := false; 129 | query.free; 130 | 131 | 132 | end; 133 | 134 | initialization 135 | TUpst.Register('upst'); 136 | 137 | end. 138 | 139 | --------------------------------------------------------------------------------