#import "IntarS.h" #ifdef GNU_RUNTIME #import #else #import #endif // IntarS // copyright Pirmin Braun 1997-2006 - pirmin@pirmin.de // all Rights reserved; #define HANDLE_SLOWDB \ if(ts>20.0){\ int maxSlowDBCount = [[[_APP configDict]ofk:@"maxslowdbcount"]intValue];\ slowDBCount++;\ LOGS(([NSSWF @"current slowDBCount: %i",slowDBCount]));\ if(maxSlowDBCount && slowDBCount > maxSlowDBCount)exit(0);\ } // weitere Kategorien @implementation Application (DB) - (BOOL)isReferencedEO:(PBEO *)eo; { // ermittelt, ob eo von einem anderen referenziert wird if(!eo)return NO; if(![eo isKindOfClass:[PBEO class]])return NO; { PBDDTable *t = [eo myTable]; NSArray *a = [t attributesReferencingMe]; int i,j; for(i=0,j=[a count];i= 100)return lma; } } } return lma; } - (NSString *)attributAuflistungForTable:(PBDDTable *)t withDoku:(BOOL)withDoku; { NSString *s = EON; int ii,jj; NSArray *a1 = [t plainAttributes]; s = [s stringByAppendingFormat:@"----Tabelle %@ hat diese Attribute:\n\n",[t dbName]]; for(ii=0,jj=[a1 count];ii%@\n",line,[pba guiName],refdTableName]; }else{ s = [s stringByAppendingFormat:@"%@ %@\n",line,[pba guiName]]; } if([pba hasVL]){ int i1,j1; s = [s stringByAppendingString:@"\tNV:::\n"]; for(i1=0,j1=[[pba vl] count];i11.0)LOGS(([NSSWF @"%03f sec. ### setFetchCond: table %@ q %@ soa %@",ts,[myTable dbName],[q description],[soa description]])); HANDLE_SLOWDB; } return YES; } - (PBEO *)nextEOForHandle:(NSString *)handle; { //liefert autoreleastes EO; // daher immer schoen mit AutoreleasePools arbeiten; // nach dem letzten wird fetch autom. endFetchingForHandle: gemacht //letzte erfolgreich verwendete channel wird gemerkt f. evt. update NSDictionary *fetchReq = [self fetchReqForHandle:handle]; PBDDTable *myTable = (PBDDTable *)[fetchReq objectForKey:SC_pbt]; NSString *entityName = [myTable dbName],*pk; NSMutableDictionary *md; PBEO *eo=nil; PBMySQLChannel *ac; if(!fetchReq || !myTable){ LOG(@"no fetchReq or table"); return nil; } ac = [fetchReq objectForKey:SC_channel]; if(![ac isFetchInProgress]){ // LOG(@"ac no fetch in progress"); [self endFetchingForHandle:handle]; return nil; } if(!(md=[ac fetchRow])){ //den naechsten key aus temp-table // LOG(@"no result for fetchRow"); [self endFetchingForHandle:handle]; }else{ //md stammt evt. aus temptable, ist aber vollstaendig; pk = [md ofk:[myTable primaryKeyName]]; eo = [self eoFromDict:md entityName:entityName]; [eo setWasFetched:YES]; } return eo; } - (NSMutableDictionary *)nextMDForHandle:(NSString *)handle; { //liefert autoreleastes md; NSDictionary *fetchReq = [self fetchReqForHandle:handle]; NSMutableDictionary *md; PBMySQLChannel *ac; if(!fetchReq)return nil; ac = [fetchReq objectForKey:SC_channel]; if(![ac isFetchInProgress]){ [self endFetchingForHandle:handle]; return nil; } if(!(md=[ac fetchRow])){ //den naechsten key aus temp-table [self endFetchingForHandle:handle]; } return md; } /////////////////////////////////////////////////////////////////////////////////////////// // EO-Umformungen /////////////////////////////////////////////////////////////////////////////////////////// - (PBEO *)eoFromDict:(NSDictionary *)d entityName:(NSString *)entityName; { PBEO *eo; eo = [[[PBEO alloc]initWithEntityName:entityName]autorelease]; if(!eo)return nil; [eo useValuesFromDictionary:d]; return eo; } - (NSMutableDictionary *)dictFromString:(NSString *)s table:(PBDDTable *)t; { // f. fixedPosition Schnittstellen: ein String wird gemaess den Tableattributen in ein Dictionary verwandelt NSArray *a = [t plainAttributes]; NSString *s1; NSRange r; PBDDAttribute *pbat; int i,j,o=0,sl; LMD; if(!FILLED(s))return lmd; if(!t)return lmd; sl = [s length]; for(i=0,j=[a count];i1.0)LOGS(([NSSWF @"%03f sec. ### getEOs: table %@ q %@ soa %@",ts,entityName,[q description],[soa description]])); HANDLE_SLOWDB; } return a; } /* code-beispiel v = [NSSWF @"select %@ from %@ where %@ = '%@'",[kps oai:1],rtn,[[MYDD tableNamedCheap:rtn] primaryKeyName],v]; v = [_APP getSingleValueAsResultFrom:v]; */ /////////////////////////////////////////////////////////////////////////////////////////// // key vergabe /////////////////////////////////////////////////////////////////////////////////////////// - (PBEO *)newAutoNumberEntryForTableNamed:(NSString *)entityName withLastKey:(BOOL)withLastKey; { PBEO *aneo; //autonumber NSString *s=@"0"; if(withLastKey){ s = [self lastKeyForTableNamed:entityName]; if(!s)return nil; } aneo = [self createEOforEN:@"autonumber"]; [aneo tvfk(entityName,@"tablename")]; [aneo tvfk(s,@"actualnumber")]; if(![self insertEO:aneo])return nil; return aneo; } - (NSString *)lastKeyForTableNamed:(NSString *)entityName; { // table ist bereits gelocked // macht nur sinn bei durchgaengig hochgezaehlten keys ohne Prefix; int i=0; PBDDTable *myTable = [MYDD tableNamed:entityName]; if(!myTable)return nil; i = [singleValueSQL(([NSSWF @"select max(%@) from %@;",[myTable primaryKeyName],entityName])) intValue]; return [NSS(i) secure0LPaddedSubstringToIndex:[[myTable primaryKeyAttr]length]]; } /////////////////////////////////////////////////////////////////////////////////////////// // low level sql /////////////////////////////////////////////////////////////////////////////////////////// - (unsigned)evaluateSQL:(NSString *)s; { //wenn kein result benoetigt wird, diese Methode nehmen //stellt sicher, dass ein eventuelles result gefreed wird und der channel damit wieder zur verfuegung steht //wird ein result benoetigt, die gleichnamige Methode am Channel aufrufen und selber dafuer sorgen, dass der fetch beendet wird; PBMySQLChannel *ac; unsigned result; double ts=0.0; if(!FILLED(s))return 0; if(!(ac = [self freshChannel])){ LOG(@"--- keinen Channel bekommen"); return 0; } if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate]; } result = [ac evaluateSQL:s]; [ac cancelFetch]; if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate] - ts; if(ts>1.0)LOGS(([NSSWF @"%03f sec. ### evaluateSQL: %@",ts,s])); HANDLE_SLOWDB; } return result; } - (NSString *)getSingleValueAsResultFrom:(NSString *)s; { // returned single Value // falls was nicht klappt, EON PBMySQLChannel *ac; NSString *rs; unsigned result; NSDictionary *d; if(!FILLED(s))return EON; if(!(ac = [self freshChannel]))return EON; // LOGS(s); result = [ac evaluateSQL:s]; if(![ac isFetchInProgress])return EON; [ac setSelectedAttributes:[ac describeResults]]; d = [ac fetchRow]; [ac cancelFetch]; if(!d)return EON; // LOGS([d description]); rs = [[d allValues]firstObject]; if(!FILLED(rs))rs=EON; return rs; } - (NSDictionary *)getDictAsResultFrom:(NSString *)s; { // returned single dictionary PBMySQLChannel *ac; unsigned result; NSDictionary *d; if(!FILLED(s))return nil; if(!(ac = [self freshChannel])){ LOG(@"keinen Channel bekommen."); return nil; } // LOGS(s); result = [ac evaluateSQL:s]; if(![ac isFetchInProgress])return nil; [ac setSelectedAttributes:[ac describeResults]]; d = [ac fetchRow]; [ac cancelFetch]; return d; } - (NSArray *)getArrayAsResultFrom:(NSString *)s; { // returned array of dictionaries PBMySQLChannel *ac; unsigned result; NSDictionary *d; LMA; if(!FILLED(s))return lma; if(!(ac = [self freshChannel]))return lma; result = [ac evaluateSQL:s]; if(![ac isFetchInProgress])return lma; [ac setSelectedAttributes:[ac describeResults]]; while((d=[ac fetchRow])){ [lma addObject:d]; } [ac cancelFetch]; return lma; } - (NSArray *)getStringArrayAsResultFrom:(NSString *)s; { NSArray *a3 = [_APP getArrayAsResultFrom:s]; //das sind dictionaries LMAN(lma3); int i3,j3; for(i3=0,j3=[a3 count];i30); } - (BOOL)unlockTables; { // if([_APP orbDebug])LOGS((@"locked tables: ()")); return ([self evaluateSQL:@"UNLOCK TABLES;"]>0); } /////////////////////////////////////////////////////////////////////////////////////////// // EO Handling /////////////////////////////////////////////////////////////////////////////////////////// - (void)copyPosFrom:(PBEO *)k1 to:(PBEO *)k2 posEn:(NSString *)posEn; { // nach PBEO *p2,*p1; NSArray *a; int i,j; if(!k1 || !k2)return; a = [self positionenFor:k1 posEn:posEn]; for(i=0,j=[a count];i insertEO; %@.",[eo description]])); } if(!eo){ LOGS(@"kein EO uebergeben"); // PRINTCURRENTSTACK; return NO; } en = [eo entityName]; myTable = [myDD tableNamed:en]; if(!myTable){ LOGS(([NSSWF @"keine solche Table:%@",en])); return NO; } //nur bei autokey versorgen if([[myTable primaryKeyAttr]isAutoPK] && ![[eo values]ofk:@"no_auto_key"]){ //noch einen anderen auto-key typ definieren: z.B. auto_increment; wird von DB versorgt; NSString *s; EOQualifier *q; NSString *formatString; int newNumber; // max. 4 Mrd NSString *autonumberName; int retryCount; int l = [[myTable primaryKeyAttr]length]; // beide tables locken; falls lock nicht erhalten, return NO; // autokey holen/anlegen, erhoehen; noch nicht updaten needsAutokey = YES; if(![self lockTables:[NSSWF @"%@, autonumber",en]]){ LOGS(([NSSWF @"INSERT %@ failed; could not acquire lock for autonumber;",[eo description]])); return NO; } [parmDict setObject:eo forKey:@"p_eo"]; [parmDict setObject:en forKey:@"p_autonumberName"]; autonumberName = [[_APP executeScriptNamed:@"autonumberNameForEO" datasource:(PBWOEditor *)self parmDict:parmDict]ofk:@"p_autonumberName"]; //rewrite autonumberName q = [EOQualifier qualifierFromDict:[NSDictionary dwok:autonumberName,@"tablename",nil,nil]]; if([q isKindOfClass:[EONothingQualifier class]]){ LOGS(([NSSWF @"INSERT %@ failed; could create qualifier for autonumber;",[[NSDictionary dwok:autonumberName,@"tablename",nil,nil] description]])); [self unlockTables]; return NO; } aneo = [[self getBasicEOs:q entityName:@"autonumber" offset:0 count:1 soa:nil]firstObject]; if(!aneo){ if(![myDD tableNamedCheap:autonumberName]){ aneo = [self newAutoNumberEntryForTableNamed:autonumberName withLastKey:NO]; }else{ aneo = [self newAutoNumberEntryForTableNamed:autonumberName withLastKey:YES]; } }else{ if(![[aneo vfk:@"actualnumber"]intValue]){ // bei 0 versuchen, bestehenden letzten Key zu ermitteln [aneo tvfk([self lastKeyForTableNamed:autonumberName],@"actualnumber")]; } } if(!aneo){ LOGS(([NSSWF @"konnte keinen neuen autonumber-Eintrag fuer %@ anlegen",autonumberName])); [self unlockTables]; return NO; } formatString = [aneo vfk:@"formatstring"]; if(!FILLED(formatString)){ // fuehrende nullen sind bloed formatString=@"%i"; }else{ formatString = [[NSCalendarDate date]descriptionWithCalendarFormat:formatString]; //falls %m, %d, %y, %Y drin sind } retryCount = 0; while(retryCount++ < 200){ NSString *sql,*testKey; newNumber = ([[aneo vfk:@"actualnumber"]intValue]+1); [aneo tvfk((NSS(newNumber)),@"actualnumber")]; // hier noch nicht; erst wenn insert des Haupt-EO geklappt hat UPDAT(aneo); //autonumberForEO script kann p_autonumber modifizieren [parmDict setObject:autonumberName forKey:@"p_autonumberName"]; [parmDict setObject:[NSSWF formatString,newNumber] forKey:@"p_autonumber"]; s = [[_APP executeScriptNamed:@"autonumberForEO" datasource:(PBWOEditor *)self parmDict:parmDict]ofk:@"p_autonumber"]; if(l<[s length]){ LOGS(([NSSWF @"primaryKey gekuerzt: %@ %@",en,s])); s = [s substringFromIndex:[s length]-l]; LOGS(s); } // hier pruefen, ob Nr. schon vergeben und solange hochzaehlen bis freie gefunden; um Luecken zu fuellen sql = [NSSWF @"select %@ from %@ where %@ = '%@' limit 1",[eo primaryKeyName],[eo entityName],[eo primaryKeyName],s]; testKey = singleValueSQL(sql); if(!FILLED(testKey))break; LOGS(([NSSWF TRANSLATION(@"%@: %@ bereits in Verwendung, suche weiter"),[eo entityName],s])); } if(retryCount >= 200){ LOGS(([NSSWF @"INSERT failed; %@ keine freie Nr. gefunden nach 200 Versuchen",[eo description]])); return NO; } [eo setPrimaryKey:s]; } if(!FILLED([eo primaryKey])){ LOGS(([NSSWF @"INSERT %@ failed; no primaryKey",[eo description]])); if(needsAutokey)[self unlockTables]; return NO; } [[eo values] tvfk(CURRENTUSER,@"cuser")]; [[eo values] tvfk(CURRENTUSER,@"luser")]; cdate = [myTable plainAttrNamed:@"cdate"]; if(cdate){ if([cdate dataTyp]==DT_DATETIME){ [[eo values] tvfk([_APP now],@"cdate")]; [[eo values] tvfk([_APP now],@"ldate")]; }else{ [[eo values] tvfk([_APP today],@"cdate")]; [[eo values] tvfk([_APP today],@"ldate")]; } } eod = [self dictFromEO:eo forKeys:nil]; //alle Werte if(![eod count]){ LOGS(([NSSWF @"INSERT %@ failed; conversion to dictionary failed;",[eo description]])); if(needsAutokey)[self unlockTables]; return NO; } if(!(ac = [self freshChannel])){ LOGS(([NSSWF @"INSERT %@ failed; no channel;",[eo description]])); if(needsAutokey)[self unlockTables]; return NO; } if(![ac insertRow:eod forTable:myTable]){ LOGS(([NSSWF @"INSERT %@ failed; (s. vorherige Meldung)",[eo description]])); if(needsAutokey)[self unlockTables]; return NO; } // hier jetzt auch autokey satz updaten, falls benoetigt // unlock tables if(needsAutokey){ UPDAT(aneo); [self unlockTables]; } // wenn es ein serial ist, den vergebenen Wert holen if([[myTable primaryKeyAttr]isSerialPK]){ if([[eo primaryKey]intValue] == 0)[eo setPrimaryKey:singleValueSQL(@"select LAST_INSERT_ID()")]; } // ist der primaryKey numerisch und gibt es ein _wcs Feld, dieses auch versorgen und updaten if([myTable hasWCS]){ [eo tvfk([eo primaryKey],([NSSWF @"%@_wcs",[myTable primaryKeyName]]))]; UPDAT(eo); } [eo setDescri:nil]; [eo setWasFetched:YES]; if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate] - ts; if(ts>1.0)LOGS(([NSSWF @"%03f sec. ### insertEO: table %@ ",ts,[eo entityName]])); HANDLE_SLOWDB; } return YES; } - (BOOL)deleteEOsQ:(EOQualifier *)q entityName:(NSString *)en; { PBDDTable *myTable; PBMySQLChannel *ac; double ts=0.0; if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate]; } myTable = [myDD tableNamed:en]; if(!myTable){ LOGS(([NSSWF @"deleteEOsQ %@ failed; no table;",en])); return NO; } if([_APP orbDebug]){ LOGS(([NSSWF @"--> deleteEOsQ %@ en:%@",[q description],en])); } if(!(ac = [self freshChannel])){ LOGS(([NSSWF @"deleteEOsQ %@ failed; no channel;",en])); return NO; } if(![ac deleteRowsDescribedByQualifier:q forTable:myTable]){ LOGS(([NSSWF @"deleteEOsQ %@ failed; (s. vorherige Meldung)",en])); return NO; } if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate] - ts; if(ts>1.0)LOGS(([NSSWF @"%03f sec. ### deleteEOsQ:%@ table %@ ",ts,[q description],en])); HANDLE_SLOWDB; } return YES; } - (BOOL)updateEO:(PBEO *)eo; { PBDDTable *myTable; NSString *en,*pk; NSDictionary *eod; PBMySQLChannel *ac; double ts=0.0; PBDDAttribute *ldate; if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate]; } if([_APP orbDebug]){ // LOGS(([NSSWF @"--> updateEO; %@.",[eo description]])); } if(!eo){ LOGS(@"kein EO uebergeben."); // PRINTCURRENTSTACK; return NO; } en = [eo entityName]; myTable = [myDD tableNamed:en]; if(!myTable){ LOGS(([NSSWF @"UPDAT %@ failed; no table",[eo description]])); return NO; } if(![[eo oldValues]count])return YES; //nix zu tun //statistic felder erst hier versorgen, wenn feststeht, dass auch andere Felder geaendert if(![[eo oldValues]ofk:@"luser"])[eo tvfk(CURRENTUSER,@"luser")]; //wenn nicht explizit geaendert... ldate = [myTable plainAttrNamed:@"ldate"]; if(ldate){ if([ldate dataTyp]==DT_DATETIME){ [eo tvfk([_APP now],@"ldate")]; }else{ [eo tvfk([_APP today],@"ldate")]; } } eod = [self dictFromEO:eo forKeys:[eo oldValues]]; if(![eod count])return YES; //nix zu tun if(!(ac = [self freshChannel])){ LOGS(([NSSWF @"UPDAT %@ failed; no channel",[eo description]])); return NO; } pk = [eo primaryKey]; if(![ac updateRow:eod forTable:myTable pk:[pk mysqlEscapedString]]){ LOGS(([NSSWF @"UPDAT %@ failed; (s. vorherige Meldung)",[eo description]])); return NO; } [[eo changedValues]removeAllObjects]; [[eo changedValues]addEntriesFromDictionary:[eo oldValues]]; //damit man in didUpdate feststellen kann, was sich geaendert hat [[eo oldValues]removeAllObjects]; [eo setDescri:nil]; if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate] - ts; if(ts>1.0)LOGS(([NSSWF @"%03f sec. ### UpdateEO: table %@ pk %@ ",ts,[eo entityName],[eo primaryKey]])); HANDLE_SLOWDB; } return YES; } //array deleten - (BOOL)deleteEOs:(NSArray *)a; { double ts=0.0; NSString *en; EOQualifier *q; PBDDTable *myTable; NSMutableArray *qa = [NSMutableArray arrayWithCapacity:100]; int i,j; PBEO *eo; PBMySQLChannel *ac; //sortenrein if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate]; } if(![a count])return YES; en = [[a firstObject]entityName]; myTable = [myDD tableNamed:en]; if(!myTable){ return NO; } if([a count]==1){ return [self deleteEO:[a firstObject]]; } if([_APP orbDebug]){ LOGS(([NSSWF @"--> delete %i EOs; %@.",[a count]])); } if(!(ac = [self freshChannel]))return NO; i=0;j=[a count]-1; while(YES){ eo = [a oai:i]; [qa addObject:[eo pkq]]; if((!(i% 100) || i==j) && i){ //i==0 wird oben abgefangen: einzel-delete q = [[[EOOrQualifier alloc]initWithQualifierArray:qa]autorelease]; [qa removeAllObjects]; if(![ac deleteRowsDescribedByQualifier:q forTable:myTable]){ return NO; } } i++; if(i>j)break; } if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate] - ts; if(ts>1.0)LOGS(([NSSWF @"%03f sec. ### deleteEOs: table %@ ",ts,en])); HANDLE_SLOWDB; } return YES; } - (BOOL)deleteEO:(PBEO *)eo; { double ts=0.0; EOQualifier *q; NSString *en; PBDDTable *myTable; PBMySQLChannel *ac; if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate]; } if([_APP orbDebug]){ LOGS(([NSSWF @"--> deleteEO; %@.",[eo description]])); } if(!eo){ LOGS(@"kein EO uebergeben."); // PRINTCURRENTSTACK; return NO; } en = [eo entityName]; myTable = [myDD tableNamed:en]; if(!myTable){ LOGS(([NSSWF @"keine solche Entity:%@",en])); return NO; } if(!(ac = [self freshChannel]))return NO; q = [eo pkq]; if(![ac deleteRowsDescribedByQualifier:q forTable:myTable]){ LOGS(([NSSWF @"DELET %@ failed; (s. vorherige Meldung)",[eo description]])); return NO; } if([_APP collectIndexStatistics]){ ts = [NSDate timeIntervalSinceReferenceDate] - ts; if(ts>1.0)LOGS(([NSSWF @"%03f sec. ### deleteEO: table %@ pk %@ ",ts,[eo entityName],[eo primaryKey]])); HANDLE_SLOWDB; } return YES; } /////////////////////////////////////////////////////////////////////////////////////////// // channel handling /////////////////////////////////////////////////////////////////////////////////////////// - (void)closeAllChannels; { int i,j; PBMySQLChannel *ac; for(i=0,j=[channelPool count];i=0;i--){ c = [channelPool objectAtIndex:i]; if([c isOpen])continue; if([c dbNr] != dbNr)continue; if(![c openChannel]){ LOGS(@"konnte alten Adaptorchannel nicht oeffnen."); [channelPool removeObjectAtIndex:i]; //mit Index; continue; } // LOGS(([NSSWF @"returning reopened channel; channelpool count =%i",[channelPool count]])); return c; } // in offenen channels einen wiederverwertbaren suchen for(i=0,j=[channelPool count];i %, ? -> _ wenn nicht escaped mit backslash if(dt == DT_CHAR){ value = [self wildCardStringFrom:value]; whereClause = [NSSWF @"(%@ %@ '%@')",key,s,[value mysqlEscapedString]]; }else{ LOGS(@"nur character-type Felder duerfen mit LIKE verglichen werden"); whereClause = EON; } // if([_APP orbDebug])LOGS(whereClause); return whereClause; } //kein like; value rewriting switch(dt){ case DT_CHAR: case DT_BOOL: break; case DT_DATE: if([value iE:EON]){ //entspricht NULL value = @"0000-00-00"; }else{ [GPBD setDBString:value]; value = [GPBD dateAsMysqlDBString]; } break; case DT_DATETIME: if([value iE:@""]){ //entspricht NULL value = @"0000-00-00 00:00:00"; }else{ [GPBD setDBString:value]; value = [GPBD dateAsMysqlDBDTString]; } break; case DT_MONEY: case DT_FLOAT: case DT_INT: if([value iE:EON]){ //entspricht NULL value = @"0"; } } whereClause = [NSSWF @"(%@ %@ '%@')",key,s,[value mysqlEscapedString]]; // if([_APP orbDebug])LOGS(whereClause); return whereClause; } LOGS(@"unbekannter Qualifier-Typ."); whereClause = EON; return whereClause; } - (NSString *)orderbyClauseFrom:(NSArray *)soa forTable:(PBDDTable *)t; { NSMutableString *obyc; int i,j=[soa count]; EOSortOrdering *eos; NSString *k,*ad; SEL sel; if(!j)return EON; obyc = [NSMutableString stringWithCapacity:100]; [obyc setString:@"order by "]; for(i=0;i Index 2334 NSString *s = [NSSWCOF [NSSWF @"%@/arialuni_cmap.txt",GLOBALCONFIGPATH]]; NSArray *a = [s componentsSeparatedByString:@"\n"]; int i,j; for(i=0,j=65535;i drumrum fuer PDF int j = [s length]; int i=0; NSMutableString *ms = [NSMutableString stringWithCapacity:(j * 4) + 3]; [ms setString:@"<"]; for(i=0,j=[s length];i"]; return ms; } - (unsigned short)cidForUnichar:(unichar)uni; { return arialuni_cmap[uni]; } - (unsigned short)widthForCid:(unsigned short)cid; { return arialuni_hmtx[cid]; } - (unsigned short)widthForUnichar:(unichar)uni; { return [self widthForCid:[self cidForUnichar:uni]]; } @end @implementation Application (CEOH) // das hier wird auch noch aufgeloest und in Scripts verlagert; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // methoden fuer verschiedene Tabellen - (NSArray *)helementv3_directChildrenOf:(PBEO *)eo; { return getEOsKnKv(@"helpdeskv3",@"parentelement",[eo primaryKey]); } - (void)helementv3_genPrimKey:(PBEO *)eo inParentEO:(PBEO *)peo; { if(!peo){ //root element return; }else{ //innerhalb parent den naechsten schluessel NSArray *a = [[self helementv3_directChildrenOf:peo]valuesForKey:@"pid"]; int i,j,lk=0; if(!a){ [eo tvfk(([NSSWF @"%@.0",[peo primaryKey]]),@"pid")]; //erstes element unter diesem parent return; } for(i=0,j=[a count];i lk)lk = lk1; } lk++; [eo tvfk(([NSSWF @"%@.%i",[peo primaryKey],lk]),@"pid")]; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (BOOL)document_isJpg:(PBEO *)document; { NSString *mt = [document vfk:@"mimetype"]; if(![mt iE:@"image/jpeg"])return NO; return YES; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - (NSArray *)zuordnungen_establishArrayZuord:(NSArray *)a1 :(NSArray *)a2 grund:(NSString *)grund inc:(BOOL)inc bemerk:(NSString *)bemerk; { int i,j,ii,jj,ic=0,fc=0; PBEO *eo1,*eo2; NSString *s; LMA; if(!a1 || !a2)return nil; if(([a1 count] * [a2 count]) > 1000){ LOGI(TRANSLATION(@"mehr als 1000 Zuordnungen auf einmal ist zuviel.")); return nil; } for(i=0,j=[a1 count];i .html NSString *hdprefix = [NSSWF @"%@/web",MANDANTPATH]; NSArray *a = [[[completeFn withoutPrefix:hdprefix] stringWithForwardSlashes]componentsSeparatedByString:@"/"]; int i,j; LMA; NSString *s; for(i=0,j=[a count];i 0){ s = [s substringFromIndex:r.location + r.length]; } if([s hasSecureSuffix:@".txt"])s = [[s stringWithoutSuffix:@".txt"]stringByAppendingString:@".html"]; [lma addObject:s]; } s = [lma componentsJoinedByString:@"/"]; if(![s hasSecurePrefix:@"/"])s = [@"/" stringByAppendingString:s]; return s; } - (NSString *)navLinesFor:(PBEO *)eo; { LMA; int i,j; NSString *url = [eo vfk:@"url"]; int nl = [[eo vfk:@"nestinglevel"]intValue]; int currentNL = 0; BOOL increasing = YES; for(i=0,j=[h3eos count];i nl){ currentNL = nl; increasing = NO; } } }else{ if(nl1 < currentNL){ [lma addObject:[self navLinkFor:eo1 eo:eo]]; currentNL--; } } } return [lma componentsJoinedByString:@""]; } - (NSString *)navLinkFor:(PBEO *)navEO eo:(PBEO *)eo; { NSString *navLinkDir = @"%@ » %@"; NSString *navLinkFile = @"%@ %@"; NSString *navLinkSelf = @"%@ %@"; NSString *nestingImage=@""; int nl = [[navEO vfk:@"nestinglevel"]intValue]; if(nl){ nestingImage = [NSSWF @"\"\"",WEBIMAGEDIR,nl*10]; } if([[navEO vfk:@"url"]iE:[eo vfk:@"url"]]){ return [NSSWF navLinkSelf,nestingImage,WEBBASEPATH,[[navEO vfk:@"url"]urlEncodedString],[navEO vfk:@"title"]]; } if([[navEO vfk:@"isfinal"]iE:@"J"]){ return [NSSWF navLinkFile,nestingImage,WEBBASEPATH,[[navEO vfk:@"url"]urlEncodedString],[navEO vfk:@"title"]]; }else{ return [NSSWF navLinkDir,nestingImage,WEBBASEPATH,[[navEO vfk:@"urlff"]urlEncodedString],[navEO vfk:@"title"]]; } } - (void)publish; { NSString *basePath = [NSSWF @"%@/web",MANDANTPATH]; NSString *web_template,*web_template_path; int i,j; BOOL first = YES; if(![myFM fileExistsAtPath:basePath]){ LOGI(([NSSWF TRANSLATION(@"basePath %@ nicht gefunden"),basePath])); return; } [allLATeX setString:[NSSWF [NSSWCOF [NSSWF @"%@/publish_template.tex",basePath]],basePath]]; [h3eos removeAllObjects]; nestinglevel = 0; gliederungsTiefe = 0; [self publishDirectory:basePath]; [allLATeX appendString:@"\\end{document}"]; [allLATeX writeToFileLatin1:[NSSWF @"%@/Webserver_Resources/web/Publish.tex",GLOBALCONFIGPATH]]; // rendern // den urlff ermitteln for(i=0,j=[h3eos count];i\n"]; if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionary:o inXML:ms forName:docType nestingLevel:0]; }else if([o isKindOfClass:[NSArray class]]){ [self encodeArray:o inXML:ms forName:docType nestingLevel:0]; }else{ LOGS(@"falsche Klasse; muss Dictionary oder Array sein"); return @""; } return ms; } - (void)encodeDictionary:(NSDictionary *)d inXML:(NSMutableString *)ms forName:(NSString *)s nestingLevel:(int)nl; { // interne Methode NSArray *a1=[d allKeys]; NSArray *a2=[d allObjects]; NSString *dictName = [s stringWithXMLEscapes]; NSString *nesting = [NSString stringWith:nl timesString:@"\t"]; int i,j; [ms appendString:[NSSWF @"%@<%@>\n",nesting,dictName]]; for(i=0,j=[a1 count];i%@\n",nesting,s1,[o stringWithXMLEscapes],s1]]; }else{ if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionary:o inXML:ms forName:k nestingLevel:nl + 1]; }else if([o isKindOfClass:[NSArray class]]){ [self encodeArray:o inXML:ms forName:k nestingLevel:nl + 1]; } } } [ms appendString:[NSSWF @"%@\n",nesting,dictName]]; } - (void)encodeArray:(NSArray *)a inXML:(NSMutableString *)ms forName:(NSString *)s nestingLevel:(int)nl; { // interne Methode NSString *arrayName = [s stringWithXMLEscapes]; NSString *nesting = [NSString stringWith:nl timesString:@"\t"]; int i,j; [ms appendString:[NSSWF @"%@<%@>\n",nesting,arrayName]]; for(i=0,j=[a count];i%@\n",nesting,[o stringWithXMLEscapes]]]; }else{ if([o isKindOfClass:[NSDictionary class]]){ [self encodeDictionary:o inXML:ms forName:@"NSArrayItem" nestingLevel:nl + 1]; }else if([o isKindOfClass:[NSArray class]]){ [self encodeArray:o inXML:ms forName:@"NSArrayItem" nestingLevel:nl + 1]; } } } [ms appendString:[NSSWF @"%@\n",nesting,arrayName]]; } - (id)objectFromXML:(NSString *)xml; { // erst den Baum aufbauen; danach analysieren und entscheiden, was Dictionaries und Arrays sind; XMLObject *rootObject = nil,*currentObject=nil; NSString *xmlname; NSRange r; r = [xml rangeOfString:@""]; if(!(r.length)){ LOGS(([NSSWF @"unmatched "]; if(!(r.length)){ LOGS(([NSSWF @"missing end of comment --> %@",[xml abbreviated60String]])); return nil; }else{ xml = [xml secureSubstringFromIndex:r.location + r.length]; } }else if([xml hasSecurePrefix:@""]; if(!(r.length)){ LOGS(([NSSWF @"missing > in endtag %@",[xml abbreviated60String]])); return nil; }else{ xmlname = [[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes]; if(!FILLED(xmlname)){ LOGS(([NSSWF @"empty Name in endtag %@ ",[xml abbreviated60String]])); return nil; } if(![xmlname iE:[currentObject name]]){ LOGS(([NSSWF @"Name %@ doesn't match name of starttag %@",[xml abbreviated60String],[currentObject name]])); return nil; } xml = [xml secureSubstringFromIndex:r.location + r.length]; // dieses Objekt ist fertig geparsed currentObject = [currentObject parent]; } }else{ // hier beginnt vermutlich ein Name xml = [xml substringFromIndex:1]; r = [xml rangeOfString:@">"]; if(!(r.length)){ LOGS(([NSSWF @"missing > %@",[xml abbreviated60String]])); return nil; }else{ xmlname = [[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes]; if(!FILLED(xmlname)){ LOGS(([NSSWF @"empty Name %@",[xml abbreviated60String]])); return nil; } if(!rootObject){ rootObject = [XMLObject xmlObjectWithName:xmlname]; currentObject = rootObject; }else{ XMLObject *o = [XMLObject xmlObjectWithName:xmlname]; [o setParent:currentObject]; [[currentObject children]addObject:o]; [currentObject setTyp:XMLObjectTyp_Container]; currentObject = o; } xml = [xml secureSubstringFromIndex:r.location + r.length]; } } }else{ [currentObject setTyp:XMLObjectTyp_Element]; // content des element r = [xml rangeOfString:@""]; if(!(r.length)){ LOGS(([NSSWF @"missing > in endtag %@",[xml abbreviated60String]])); return nil; }else{ xmlname = [[xml secureSubstringToIndex:r.location]stringBySubstitutingXMLEscapes]; if(!FILLED(xmlname)){ LOGS(([NSSWF @"empty Name in endtag %@",[xml abbreviated60String]])); return nil; } if(![xmlname iE:[currentObject name]]){ LOGS(([NSSWF @"Name %@ doesn't match name of starttag %@",[xml abbreviated60String],[currentObject name]])); return nil; } xml = [xml substringFromIndex:r.location + r.length]; // dieses Objekt ist fertig geparsed currentObject = [currentObject parent]; } } } } if(!rootObject){ LOGS(@"no rootObject in xml"); return nil; } if([rootObject typ]==XMLObjectTyp_Element){ LOGS(@"rootObject ist kein Container-Objekt"); return nil; } // jetzt den Baum analysieren if([rootObject determineConreteContainer]){ if([rootObject ma])return [rootObject ma]; if([rootObject md])return [rootObject md]; } return nil; } - (NSData *)httpGet:(NSString *)uri host:(NSString *)host; { NSMutableData *response = [NSMutableData dataWithCapacity:4096]; PBSocket *socket; if(!FILLED(uri) || !FILLED(host)){LOGS(@"no host/uri"); return response;} if(!(socket = [PBSocket socket])){LOGS(@"no socket"); return response;} [socket connectToHostName:host port:80]; if(![socket connected]){LOGS(@"no connect"); return response;} [socket writeString:[NSSWF @"GET %@ HTTP/1.0\r\nHost: %@\r\n\r\n",uri,host]]; [socket readData:response]; return response; } - (NSData *)httpPost:(NSString *)uri host:(NSString *)host soa:(NSString *)soa parm:(NSDictionary *)parm docType:(NSString *)docType; { // soa ist der optionale Name eines soa-Aufrufes; in Aprica ist dies ein Script-Name; // parm ist ein Dictionary, das in XML umgewandelt zum host transportiert wird // docType ist der optionale Name des XML-Dokuments; falls leer, wird ein default genommen; NSMutableData *response = [NSMutableData dataWithCapacity:4096]; PBSocket *socket; NSMutableString *ms = [NSMutableString stringWithCapacity:4096]; // hier wird der request zusammengebaut if(!FILLED(uri) || !FILLED(host)){LOGS(@"no host/uri"); return response;} if(!(socket = [PBSocket socket])){LOGS(@"no socket"); return response;} [socket connectToHostName:host port:80]; if(![socket connected]){LOGS(@"no connect"); return response;} [ms setString:[NSSWF @"POST %@ HTTP/1.0\r\n",uri]]; [ms appendString:[NSSWF @"Host: %@\r\n",host]]; if(FILLED(soa)){ [ms appendString:[NSSWF @"soa: %@\r\n",soa]]; // ein zusaetzlicher Header nimmt das Kommando auf } if(parm){ NSString *xml; if(!FILLED(docType))docType = @"pirmin"; xml = [self encodeObject:parm withDocType:docType]; [ms appendString:[NSSWF @"Content-Length: %i\r\n\r\n",[xml length]]]; [ms appendString:xml]; }else{ [ms appendString:@"Content-Length: 0\r\n\r\n"]; } if(log_changes)LOG(ms); [socket writeString:ms]; [socket readData:response]; return response; } @end