#import "Aprica.h"
// Aprica2
// copyright Pirmin Braun 1997-2007 - pirmin@pirmin.de
// all Rights reserved;
@implementation Session
ACCESSClassm(ueo, setUeo, PBEO)
ACCESSm(userName,setUserName)
ACCESSm(lastContextID,setLastContextID);
ACCESSClassm(modulToClose, setModulToClose, PBWOEditor)
ACCESSClassm(nextModul, setNextModul, PBWOEditor)
ACCESSm(confirmString,setConfirmString)
ACCESSm(confirmBack,setConfirmBack)
ACCESSm(confirmContinue,setConfirmContinue)
ACCESSm(cs_v,setCs_v);
ACCESSClassm(cs_a, setCs_a, NSArray)
ACCESSClassm(cs_datasource, setCs_datasource, PBWOEditor)
ACCESSClassm(cs_p_parmDict, setCs_p_parmDict, NSMutableDictionary)
ACCESSClassm(cs_stack, setCs_stack, NSMutableArray)
ACCESSClassm(cs_varDictStack, setCs_varDictStack, NSMutableArray)
ACCESSClassm(cs_foreachStack, setCs_foreachStack, NSMutableArray)
ACCESSClassm(cs_varDict, setCs_varDict, NSMutableDictionary)
ACCESSClassm(cs_localVarDict, setCs_localVarDict, NSMutableDictionary)
ACCESSm(cs_lookupName,setCs_lookupName);
ACCESSm(_rv,set_rv)
ACCESSm(lastLogin,setLastLogin)
ACCESSm(use_lif_from,setUse_lif_from)
- (BOOL)dialogMode;{return dialogMode;}- (void)setDialogMode:(BOOL)yn;{dialogMode = yn;}- (BOOL)dialogSubMode0; {return (dialogSubMode==0);}- (BOOL)dialogSubMode1; {return (dialogSubMode==1);}- (BOOL)mayConfig;{ return (!use_lif_from);}- (int)dialogSubMode; {return dialogSubMode;}- (void)setDialogSubMode:(int)i; { dialogSubMode=i;}- (int)cs_i; {return cs_i;}- (void)setCs_i:(int)i;{cs_i = i;}- (int)cs_j; {return cs_j;}- (void)setCs_j:(int)i;{cs_j = i;}- (int)cs_stc; {return cs_stc;}- (void)setCs_stc:(int)i;{cs_stc = i;}- (BOOL)cs_debug;{return cs_debug;}- (void)setCs_debug:(BOOL)yn;{cs_debug = yn;}- init;
{ int to;
if(!(self = [super init]))return nil;
#warning configurierbar machen
// [self setStoresIDsInCookies:YES];
[self setUserName:nil];
[self setUeo:nil];
scriptStackDepth = 0;
to = [[[_APP configDict]ofk:@"sessiontimeout"]intValue];
if(!to)to=600; // 10 min default
[self setTimeOut:to];
MD(instanceDict);
MD(dead);
MA(launchedModuls);
MD(bundlesByName);
MD(bundlesByKuerzel);
MD(parmDict);
MD(moduleSoseq);
MA(errors);
oldContextRequested = NO;
[self setLastContextID:nil];
dialogMode = NO;
dialogSubMode = 0;
LOGS((@"new session created..."));
// PRINTCURRENTSTACK;
return self;
}
- (void)loadSoseq;
{// den Inhalt aus ueo.soseq ins moduleSoseq Dictionary
NSArray *a = [[ueo vfk:@"soseq"]componentsSeparatedByString:@"\n"];
int i,j;
[moduleSoseq removeAllObjects];
for(i=0,j=[a count];i<j;i++){ NSArray *a1 = [[a oai:i]componentsSeparatedByString:@"="];
if([a1 count]==2){ [moduleSoseq setObject:[a1 oai:1] forKey:[a1 oai:0]];
}
}
}
- (void)saveSoseq;
{// den Inhalt aus moduleSoseq Dictionary ins ueo.soseq und dieses updaten
LMA;
NSArray *a1 = [moduleSoseq allKeys];
NSArray *a2 = [moduleSoseq allObjects];
int i,j;
for(i=0,j=[a1 count];i<j;i++){ [lma addObject:[NSSWF @"%@=%@",[a1 oai:i],[a2 oai:i]]];
}
[ueo tvfk([lma componentsJoinedByString:@"\n"],@"soseq")];
UPDAT(ueo);
}
- initWithUserEO:(PBEO *)u;
{ int to;
if(!u)return nil;
[self setUeo:u];
[self setUserName:[ueo primaryKey]];
//steuert, ob gui oder dbName angezeigt wird; normalerweise guiname; f. Reports designen aber auch dbName interessant;
isRoot = [[ueo vfk:@"sonderberechtigung"] iE:@"root"];
isGruppe0 = [[ueo vfk:@"gruppe0"] iE:@"J"];
isGruppe1 = [[ueo vfk:@"gruppe1"] iE:@"J"];
isGruppe2 = [[ueo vfk:@"gruppe2"] iE:@"J"];
isGruppe3 = [[ueo vfk:@"gruppe3"] iE:@"J"];
isGruppe4 = [[ueo vfk:@"gruppe4"] iE:@"J"];
isGruppe5 = [[ueo vfk:@"gruppe5"] iE:@"J"];
isGruppe6 = [[ueo vfk:@"gruppe6"] iE:@"J"];
isGruppe7 = [[ueo vfk:@"gruppe7"] iE:@"J"];
isGruppe8 = [[ueo vfk:@"gruppe8"] iE:@"J"];
isGruppe9 = [[ueo vfk:@"gruppe9"] iE:@"J"];
[self setUse_lif_from:[ueo vfk:@"use_lif_from"]];
if(!FILLED(use_lif_from))[self setUse_lif_from:nil];
readOnly = [[ueo vfk:@"sonderberechtigung"] iE:@"gdpdu"] || [[ueo vfk:@"sonderberechtigung"] iE:@"rop"];
lang = [[ueo vfk:@"lang"] intValue]; //lang haengt am usereo
lang_script = lang;
to = [[ueo vfk:@"sessiontimeout"] intValue];
if (to){ if(to < 600)to=600;
[self setTimeOut: to];
}
[self registerUserBundles]; //User-Berechtigungen muessen bekannt sein dafuer
[self loadSoseq];
[parmDict setObject:[_APP browserTitle] forKey:@"browserTitle"]; // kann dann ueberschrieben werden von didLogin
[_APP executeScriptNamed:@"_Application/didLogin" datasource:(PBWOEditor *)self parmDict:parmDict];
return self;
}
- (NSMutableDictionary *)parmDict;
{ return parmDict;
}
- (NSMutableDictionary *)moduleSoseq;
{ return moduleSoseq;
}
- (NSDictionary *)gatherBerechtForUser:(PBEO *)u;
{ int i,ii,jj;
LMD;
NSString *gs;
if((gs = [[u values]ofk:@"gruppenstring"])){// neues verfahren
NSArray *bs = [_APP availableBundles];
PBWOBundle *b;
BOOL gx[10];
// fuer nix berechtigt
if([gs iE:@"----------"])return lmd;
for(i=0;i<ANZ_GRUPPEN;i++){ gx[i]=[[[gs charAt:i]lowercaseString]iE:@"x"];
}
for(ii=0,jj=[bs count];ii<jj;ii++){ b = [bs oai:ii];
gs = [b gruppenstring];
if([gs iE:@"----------"])continue;
for(i=0;i<ANZ_GRUPPEN;i++){ if(gx[i] && [[[gs charAt:i]lowercaseString]iE:@"x"]){ [lmd setSecureObject:@"x" forKey:[b name]];
break;
}
}
}
}
return lmd;
}
- (Application *)application;
{ return _APP;
}
- (BOOL)isRoot;
{ return isRoot || isTemporaryRoot;
}
- (BOOL)isTemporaryRoot;
{ return isTemporaryRoot;
}
- (void)setIsTemporaryRoot:(BOOL)yn;
{ isTemporaryRoot = yn;
}
- (BOOL)readOnly;
{ return readOnly;
}
- (int)scriptStackDepth;{return scriptStackDepth;}- (void)inc_scriptStackDepth;{scriptStackDepth++;}- (void)dec_scriptStackDepth;{if(scriptStackDepth > 0)scriptStackDepth--;}- (WOElement *)invokeActionForRequest:(WORequest *)aRequest inContext:(WOContext *)aContext;
{ if(oldContextRequested)return nil;
return [super invokeActionForRequest:aRequest inContext:aContext];
}
/*f. debugging
- retain;
{ PRINTCURRENTSTACK;
return [super retain];
}
*/
- (void)dealloc;
{ //wird autom. aufgerufen, wenn timeout
[_APP executeScriptNamed:@"_Application/didLogout" datasource:(PBWOEditor *)self parmDict:parmDict];
[_APP sessionEnded:[self sessionID]];
if ([_APP currentSession] == self) [_APP setCurrentSession: nil];
[modulToClose release];
[nextModul release];
[bundlesByName release];
[bundlesByKuerzel release];
[use_lif_from release];
[dead release];
[errors release];
[instanceDict release];
[lastContextID release];
[lastLogin release];
[launchedModuls release];
[ueo release];
[userName release];
[parmDict release];
[moduleSoseq release];
[_rv release];
[confirmString release];
[confirmBack release];
[confirmContinue release];
[cs_v release];
[cs_a release];
[cs_datasource release];
[cs_p_parmDict release];
[cs_stack release];
[cs_varDictStack release];
[cs_foreachStack release];
[cs_varDict release];
[cs_localVarDict release];
[cs_lookupName release];
[super dealloc];
}
- (void)awake
{// LOGS(([NSSWF @"%@ awake",[self sessionID]]));
[_APP setCurrentSession:self];
}
- (void)sleep;
{ [errors removeAllObjects];
[self setConfirmString:nil];
[self setModulToClose:nil]; // released das dann
[_APP setCurrentSession:nil];
[super sleep];
}
- instanceForBundle:(PBWOBundle *)aBundle
{ if(!aBundle){ LOGS(@"kein bundle uebergeben");
// PRINTCURRENTSTACK;
return nil;
}
return [self instanceForBundleNamed:[aBundle name]];
}
- instanceForBundleNamed:(NSString *)bundleName;
{// neuer Standard: Module heissen so wie die Tabelle, die sie verwalten
id e = [self instanceForBundleNamed:bundleName fromApp:NO];
if(e)return e;
// alte Namenskonvention
e = [self instanceForBundleNamed:[bundleName capitalizedString] fromApp:NO];
if(e)return e;
return [self instanceForBundleNamed:[[bundleName capitalizedString]stringByAppendingString:@"E"] fromApp:NO];
}
- instanceForAppBundleNamed:(NSString *)bundleName;
{ return [self instanceForBundleNamed:bundleName fromApp:YES];
}
- instanceForBundleNamed:(NSString *)bundleName fromApp:(BOOL)fromApp;
{ return [self instanceForBundleNamed:bundleName fromApp:fromApp additional:NO];
}
- instanceForBundleNamed:(NSString *)bundleName fromApp:(BOOL)fromApp additional:(BOOL)additional;
{ PBWOBundle *b;
PBWOEditor *anInstance = nil;
BOOL rc = YES;
if(!bundleName){ LOGS(@"kein bundleName uebergeben");
// PRINTCURRENTSTACK;
return nil;
}
if([dead ofk:bundleName]){ LOGS(@"bundle schonmal gestorben");
return nil; // schonmal fehlgeschlagen
}
if(additional || !(anInstance = [instanceDict ofk:bundleName])){ // nur wenn user berechtigt f. bundle:
if(fromApp){ b=[_APP bundleWithName:bundleName];
}else{ b=[self bundleWithName:bundleName];
}
if(b){ if([_APP logActions]){ LOGS(([NSSWF @"%@ %@ %@",bundleName,[b principalClassName],CURRENTUSER]));
}
NS_DURING;
anInstance = (PBWOEditor *)[_APP pageWithName:[b principalClassName] inContext:[self context]];
if(anInstance){ if([_APP logActions])LOGS(@"got Instance");
[anInstance setUpWithBundle:b];
[instanceDict setSecureObject:anInstance forKey:bundleName];
if(![b hiddenModul]){ [launchedModuls addObject:anInstance];
}
}else{ LOGS(([NSSWF @"pageWithName:%@ failed",bundleName]));
// PRINTCURRENTSTACK;
rc = NO;
}
NS_HANDLER;
LOGS_Ex(EON);
rc=NO;
NS_ENDHANDLER;
if(!rc){ LOGI(([NSSWF TRANSLATION(@"konnte Modul %@ nicht laden. html, wod?"),bundleName]));
[instanceDict removeObjectForKey:bundleName];
[dead setSecureObject:bundleName forKey:bundleName];
return nil;
}
}else{ return nil;
}
}
[anInstance ensureAwakeInContext:[self context]];
[anInstance callingModul];
return anInstance;
}
- (NSDictionary *)instanceDict;
{ return instanceDict;
}
- (NSArray *)launchedModuls;
{ return (NSArray *)launchedModuls;
}
- (void)appendToResponse:(WOResponse *)aResponse inContext:(WOContext *)aContext;
{ NSString *si;
[self setLastContextID:[aContext contextID]];
[super appendToResponse:aResponse inContext:aContext];
if((si=[self sessionID])){ WORequest *aRequest = [aContext request];
NSString *time = [[NSCalendarDate date] descriptionWithCalendarFormat:@"%H:%M:%S (%d.%m.%Y)"];
NSString *s1;
s1 = [NSSWF@"%@ %@ %@ %@",time,[aRequest headerForKey:@"x-webobjects-remote-host"],[aRequest headerForKey:@"x-webobjects-remote-addr"],si];
// hier kann jeder zugriff ueberwacht werden LOGS(s1);
}
}
- (NSString *)userLoginName
{ return userName;
}
- (void)registerUserBundles;
{// bundlesByName und bundlesByKuerzel fuellen gemaess den festgestellten Berechtigungen
NSArray *bs = [_APP availableBundles];
PBWOBundle *b;
int i,j;
NSDictionary *d = [self gatherBerechtForUser:ueo]; // holt berechtigte modulnamen
[bundlesByName removeAllObjects];
[bundlesByKuerzel removeAllObjects];
for(i=0,j=[bs count];i<j;i++){ NSString *kuerzel;
b = [bs oai:i];
//editierberechtigung schliesst sichtbar-berechtigung natuerlich mit ein
//gruppenberechtigung und Userberechtigung; nur wenn gar nichts, wird modul ausgeblendet
if([self isRoot])goto takeIt;
if([d ofk:[b name]])goto takeIt; //namen aller berechtigten
if([b publicModul])goto takeIt; //public
continue;
takeIt:
[bundlesByName sofk(b,[b name])];
kuerzel = [b kuerzel];
if(FILLED(kuerzel)){ [bundlesByKuerzel sofk(b,kuerzel)];
}
}
}
- (PBWOEditor *)instanceForKuerzel:(NSString *)kuerzel;
{ PBWOBundle *b;
if(!kuerzel)return nil;
b = [bundlesByKuerzel ofk:kuerzel];
if(!b)return nil;
return [self instanceForBundle:b];
}
- (NSArray *)availableBundles;
{ return [bundlesByName allValues];
}
- (PBWOBundle *)bundleWithName:(NSString *)name
{ return [bundlesByName ofk:name];
}
- (NSArray *)bundlesForSuchString:(NSString *)s;
{ NSArray *a = [self availableBundles];
int i,j=[a count];
LMA;
PBWOBundle *b;
NSString *ss=[s simplyfiedString],*mc;
if(!FILLED(ss))return (NSArray *)lma;
for(i=0;i<j;i++){ b = [a oai:i];
mc = [b matchCode];
if(!FILLED(mc))continue;
if(!([mc rangeOfString:ss].length))continue;
if([b hiddenModul])continue;
[lma addObject:b];
if([lma count]>20)return lma; //max menge;
}
return (NSArray *)lma;
}
- (int)preferredLangForISOLanguages:(NSArray *)a;
{ static NSDictionary *langmap = nil;
NSString *s = nil;
unsigned i,j;
if (!langmap) langmap = [[@"{ de = 0; en = 1; pl = 2; zh = 3; ru = 4; it = 5; fr = 6; cs = 7; es = 8; hu = 9; }" propertyList] retain]; for (i=0,j=[a count];i<j;i++) { if ((s=[langmap ofk: [[[a oai:i] secureSubstringToIndex:2] lowercaseString]])) break;
}
return [s intValue];
}
- (int)lang;{return lang;}- (void)setLang:(int)i;
{ lang = i;
}
- (int)lang_script;{return lang_script;}- (void)setLang_script:(int)i;
{ lang_script = i;
}
- (NSString *)transFor:(NSString *)s;
{//liefert translation f. sprache des users
if(lang == 0)return s;
return [self transFor:s lang:lang];
}
- (NSString *)transScriptFor:(NSString *)s;
{//liefert translation f. sprache des script
if(lang_script == 0)return s;
return [self transFor:s lang:lang_script];
}
- (NSString *)transFor:(NSString *)ps lang:(int)lng;
{//liefert translation f. sprache lng
// neue fehlende in translationsm speichern;
NSString *s,*s1;
PBEO *eo;
if(lng == 0)return ps;
s = [ps stringWithoutLeadingWhiteSpace];
s = [s stringWithoutTrailingWhiteSpace]; // Bug in MySQL:Trailing white space geht beim speichern verloren
if(!FILLED(s)) return ps;
s1 = [[_APP transDict] ofk:s];
if(!s1){ NSString *sql,*result;
[[_APP transDict] setObject:EON forKey:s]; //gleich aufnehmen
sql = [NSSWF @"select text0 from translationsm where text0 = BINARY '%@'",s];
result = singleValueSQL(sql);
if(!FILLED(result)){// LOGS(([NSSWF @">%@< >%@< >%@<",ps,s,result]));
eo = NEW_EO(@"translationsm");
[eo tvfk(s,@"text0")];
INSRT(eo);
}
return ps;
}
if(FILLED(s1))return s1;
return ps;
}
- (void)takeValuesFromRequest:(WORequest *)aRequest inContext:(WOContext *)aContext;
{ if(oldContextRequested)return; //wg. F5-Feldloeschungen und vor/zurueck
[super takeValuesFromRequest:aRequest inContext:aContext];
}
- (WOComponent *)restorePageForContextID:(NSString *)contextID;
{ // LOGS(([NSSWF @"contextID:%@ lastContextID:%@ ",contextID,lastContextID]));
// return nil; //erzeugt handlePageRestorationErrorInContext
// LOGS([[self valueForKey:@"_contextRecords"]description]);
if(lastContextID && ![lastContextID iE:contextID]){ oldContextRequested = YES; // take values und invokeAction abgeschaltet
}else{ oldContextRequested = NO;
}
return [super restorePageForContextID:lastContextID]; //immer die zuletzt gesendete Seite; F5 und backtracking verhindern
}
//aus pbwobrowser:
- (void)clearErrors;
{ [errors removeAllObjects];
}
- (NSString *)ip_adresse;
{ if([_APP isBatch]) return @"127.0.0.1";
#ifdef GNUSTEP
return [[[self context] request] headerForKey:@"x-gsweb-remote-addr"];
#else
return [[[self context] request] headerForKey:@"x-webobjects-remote-addr"];
#endif
}
- (NSString *)serverName;
{ NSString *ip_adresse = [self ip_adresse];
NSString *subn = [[_APP configDict]ofk:@"internsubnet"];
// LOGS(([NSSWF @"ipadr:%@ subnet:%@",ip_adresse,subn]));
if([ip_adresse iE:@"127.0.0.1"] || [ip_adresse hasSecurePrefix:subn]){ //nicht ganz korrekt; bit-mask waere besser NSString *sn = [[_APP configDict]ofk:@"servername"];
if(FILLED(sn))return sn; //in configDict festlegen, anstatt httpd.conf zu editieren
}else{ NSString *snx = [[_APP configDict]ofk:@"servernamex"]; //kommt von extern
if(FILLED(snx))return snx; //in configDict festlegen, anstatt httpd.conf zu editieren
}
return [[[self context] request]headerForKey:@"x-webobjects-server-name"]; //aus dem apache httpd.conf
}
- (NSMutableArray *)errors;
{ return errors;
}
- (void)addMsg:(NSString *)s;
{ if(!s)return;
LOGS(s); // in ereignisanzeige
if([errors count]>10)return;
if([errors count]==10){ [errors addObject:TRANSLATION(@"... (weitere Meldungen unterdrueckt)")];
return;
}
if(NSNotFound == [errors indexOfObject:s]) [errors addObject:s];
}
- (void)removeFromPersonal:(PBWOEditor *)pbv;
{ LMA;
if(!pbv)return;
[lma addObjectsFromArray:[[ueo vfk:@"prestartingmod"]componentsSeparatedByString:@","]];
[lma removeObject:[pbv name]];
[ueo tvfk([lma componentsJoinedByString:@","],@"prestartingmod")];
UPDAT(ueo);
}
- (void)addToPersonal:(PBWOEditor *)pbv;
{ LMA;
if(!pbv)return;
if([[pbv bundle] hiddenModul])return;
[lma addObjectsFromArray:[[ueo vfk:@"prestartingmod"]componentsSeparatedByString:@","]];
if([lma count]>MAXHISTENTRIES)[lma secureRemoveLastObject];
[lma insertObject:[pbv name] atIndex:0];
[ueo tvfk([lma componentsJoinedByString:@","],@"prestartingmod")];
UPDAT(ueo);
}
- (Session *)session;
{// fuer scripting %session
return self;
}
- (NSStringEncoding)preferredEncoding;
{ //TODO: Encoding sollte wahrscheinlich entweder in der APP oder beim USER
// definiert werden. Zunaechst unterscheiden wir nur UTF8/ISOLatin1
return ([_APP utf8])?NSUTF8StringEncoding:NSWindowsCP1252StringEncoding;
}
@end