void FuncSet2::triggerFunc() { if(brd == NULL) { safePrint(paper, "brd is NULL\n"); return; } vector< pair<int,int> > ans; safePrint(paper, "Type\tGainSquare\tCostSquares\n"); int winValue = threatSpaceSearch(brd, turn, ans, paper); if(paper == NULL) return; paper->print("\n%s %s\n", (turn==BLACK)?"BLACK":"WHITE", (winValue==WIN)?"WIN":"NOWIN"); paper->print("threat seq = "); for(int i=0; i<ans.size(); i++) paper->print("(%d,%d) ", ans[i].first, ans[i].second); paper->print("\n\n"); paper->changeColor(); paper->moveCusorToTheEnd(); }
void FuncSet4::triggerFunc() { if(brd == NULL) { safePrint(paper, "brd is NULL\n"); return; } if(root!=NULL) root->~QTreeWidgetItem(); root = new QTreeWidgetItem(); pnSearchTree.addTopLevelItem(root); pair<int,int> *ans = new pair<int,int>(); pnsNode *rootNode; int winValue = getTruthByPNS(brd, turn, turnTobeProved, true, ans, NULL, &rootNode); buildTreeWidgetItem(rootNode, root); //printTreePnDn(rootNode, paper); if(paper == NULL) return; paper->print("winValue = %s\n", (winValue==WIN)?"WIN":"NOWIN"); paper->print("(x,y) = (%d,%d)\n", ans->first, ans->second); paper->changeColor(); paper->moveCusorToTheEnd(); }
void printWinningTree(pnsNode *node, Paper *paper) { if(paper == NULL) return; safePrint(paper, "%d,%d ", node->x, node->y); safePrint(paper, "("); int flag = 0; for(uint i=0; i<node->actualChildren.size();i++) if(node->actualChildren[i]->pn==0){ flag = 1; printWinningTree( node->actualChildren[i], paper); } if(flag == 0){ if( node->actualChildren.size() == 0 ){ safePrint(paper, "<< "); for(int i=0; i<node->winningSeq.size(); i++) safePrint(paper, "%d,%d ", node->winningSeq[i].first, node->winningSeq[i].second); safePrint(paper, ">>"); }else err(false, "printWinningTree(): cant find the next winning step, should be an error in pnSearch"); } safePrint(paper, ")"); }
int getTruthByPNS( BoardData *brd, int turn, int turnToBeProved, bool runTSS, // if is true => run TSS => need ans pair<int,int> *ans, Paper *paper, pnsNode** rootNode) { if(runTSS) safePrint(paper, "\n######################################\n"); else safePrint(paper, "\n..............¡õpnSearch(%d,%d)...............\n",turn,turnToBeProved); pnsNode *root = new pnsNode(new BoardData(brd), turn); if(rootNode!=NULL) *rootNode = root; pnsNode *fakeRoot; if(turn==turnToBeProved) fakeRoot=root; else { fakeRoot = new pnsNode(new BoardData(brd), turnToBeProved); root->parent = fakeRoot; fakeRoot->actualChildren.push_back(root); } // most-proving-node pnsNode *mpn = root; int cnt=0; // (pn==0 || dn==0) means the result has been found while( root->pn!=0 && root->dn!=0 ){ if( runTSS==false ) { if(cnt>maxLoopCnt){ root->pn=PNS_INFINITY; root->dn=0; break; }else cnt++; } mpn = proofNumberSearch(mpn, turnToBeProved, runTSS, paper); //if( mpn==NULL ) mpn = root; mpn=root; #ifdef PRINT_PNSEARCH_DETAIL printTreePnDn(root, paper); safePrint(paper, "\n"); #endif } // if tss is included => overall pns => need an answer if(runTSS && root->pn==0){ // find the answer (one step) int flag = 0; for(uint i=0; i<root->actualChildren.size();i++) if(root->actualChildren[i]->pn==0){ flag = 1; //ans = & (make_pair(root->actualChildren[i]->x, root->actualChildren[i]->y) ); //ans = new pair<int,int>(make_pair(root->actualChildren[i]->x, root->actualChildren[i]->y) ); //safePrint(paper, " (%d,%d)\n", ans->first, ans->second); if(ans==NULL) err(true, "in proofNumberSearch(), ans should not be NULL"); ans->first = root->actualChildren[i]->x; ans->second = root->actualChildren[i]->y; } if(flag == 0){ if( root->actualChildren.size() == 0 ){ //ans = & (make_pair(root->winningSeq[0].first, root->winningSeq[0].second) ); //ans = new pair<int,int>(make_pair(root->winningSeq[0].first, root->winningSeq[0].second) ); //safePrint(paper, " (%d,%d)\n", ans->first, ans->second); if(ans==NULL) err(true, "in proofNumberSearch(), ans should not be NULL"); if(root->winningSeq.size()==0) err(true, "getTruthByPNS(): root->winningSeq.Size==0, should be an error in pnSearch"); ans->first = root->winningSeq[0].first; ans->second = root->winningSeq[0].second; }else err(false, "getTruthByPNS(): cant find the next winning step, should be an error in pnSearch"); } } // print result //brd->printBoard(); safePrint(paper, "turn = %d, pnSearchResult = %s \n", turn, (root->pn==0)? "WIN" : "LOSE"); if(root->pn == 0) printWinningTree(root, paper); // if WIN, print win seq safePrint(paper, "\n"); if(runTSS) safePrint(paper, "######################################\n"); else safePrint(paper, "..............¡ôpnSearch...............\n"); return ( (root->pn==0)? (WIN) : (NOWIN) ); }
pnsNode* proofNumberSearch(pnsNode *node, int rootTurn, bool runTSS, Paper *paper) { if(node==NULL) err(true, "proofNumberSearch() parameter value error: [node] shouldn't be NULL."); /*************************************************** * virtualChildren is empty : node is a leaf (a temp terminal node) ***************************************************/ if(node->virtualChildren.size()==0 && node->actualChildren.size() ==0) { if(node->pn!=1 || node->dn!=1) err(true, "proofNumberSearch(): terminal pnsNode pn/dn value error"); // different action varies by "runTSS" int winValue = NOWIN; if(runTSS){ // run evaluation function, record the winning seq found by threatSpaceSearch winValue = threatSpaceSearch(node->brd, node->turn, node->winningSeq, paper); if(g_pnAgain==0 && winValue!=WIN && node->turn == opposite(rootTurn) ){ pair<int, int> ans; g_pnAgain=1; int tmpWinValue = getTruthByPNS(node->brd, node->turn, opposite(node->turn), true, &ans); g_pnAgain=0; if(tmpWinValue==WIN) winValue = LOSE; } }else { // find all (turn)'s threats which are bigger than opn Threat *opn = findMaxThreat( node->brd, opposite(node->turn), false ); vector< Threat* > my = findAllThreat(node->brd, node->turn, true, opn); #ifdef PRINT_PNSEARCH_DETAIL safePrint(paper, ">>>>>>>>>>>>>>>>>>>\n"); if(opn!=NULL) opn->printThreat(paper); if(my.size()!=0) my[0]->printThreat(paper); safePrint(paper, ">>>>>>>>>>>>>>>>>>>\n"); #endif if(my.size()!=0 && (my[0]->type==Five || my[0]->type==StrF) )winValue=WIN; else winValue=NOWIN; } if( winValue == WIN ){ // find WIN => this node is a real terminal node if(node->turn == rootTurn){ node->pn = 0; node->dn = PNS_INFINITY; }else{ node->pn = PNS_INFINITY; node->dn = 0; } #ifdef PNSTEST safePrint(paper, "=> WIN,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn); #endif // pn/dn has changed, // update parents' pn/dn ( 1 = the original pn/dn value ) // and return new most-proving-node return updatePnDn(node, 1, 1, rootTurn);; }else if(winValue == LOSE){ // means that node->turn is lost if(node->turn == rootTurn){ node->pn = PNS_INFINITY; node->dn = 0; }else{ node->pn = 0; node->dn = PNS_INFINITY; } // pn/dn has changed, // update parents' pn/dn ( 1 = the original pn/dn value ) // and return new most-proving-node #ifdef PNSTEST printf("=> LOSE,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn); #endif return updatePnDn(node, 1, 1, rootTurn); }else{ // => this node is not a real terminal node => expand its virtualChildren node->virtualChildren = availableMove(node->brd, node->turn); /******************************************************* * for faster: rootTurn's cut * cut children to only squares who form threat * ****************************************************/ /* if(node->turn == rootTurn){ vector< pair<int,int> > threatList=attackMove(node->brd,node->turn); if(threatList.size()!=0) node->virtualChildren = threatList; }*/ /*******************************************************/ if(node->virtualChildren.size()==0){ // means that node->turn has no move, is lost if(node->turn == rootTurn){ node->pn = PNS_INFINITY; node->dn = 0; }else{ node->pn = 0; node->dn = PNS_INFINITY; } // pn/dn has changed, // update parents' pn/dn ( 1 = the original pn/dn value ) // and return new most-proving-node #ifdef PNSTEST safePrint(paper, "=> LOSE,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn); #endif return updatePnDn(node, 1, 1, rootTurn); }else if(node->turn == rootTurn){ /****** max node ******/ // pn = min( all child.pn ) = 1 == original node->pn // dn = sum( all child.dn ) node->dn = node->virtualChildren.size(); #ifdef PNSTEST safePrint(paper, "=> leaf,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn); #endif // both pn/dn hasn't changed, most-proving-node is still under this tree if( node->dn==1 ) return node; else { // dn has changed, (pn hasn't) // update parents' dn ( 1 = the original dn value ) // and return new most-proving-node return updatePnDn(node, 1, 1, rootTurn); } }else{ /****** min node ******/ // dn = min( all child.dn ) = 1 == original node->dn // pn = sum( all child.pn ) node->pn = node->virtualChildren.size(); #ifdef PNSTEST safePrint(paper, "=> leaf,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn); #endif // both pn/dn hasn't changed, most-proving-node is still under this tree if( node->pn==1 ) return node; else { // pn has changed, // update parents' pn ( 1 = the original pn value ) // and return new most-proving-node return updatePnDn(node, 1, 1, rootTurn); } } } } /*************************************************** * node is an internal node ***************************************************/ pnsNode *successor = NULL; if( node->actualChildren.size()!=0 ) // the actualChildren in the end of actualChildren[] has min pn/dn successor = node->actualChildren[ node->actualChildren.size()-1 ]; if( successor==NULL || //actualChildren.size()==0 // in max node, the child who has min pn is the successor ( node->turn==rootTurn && successor->pn!=node->pn ) || // in min node, the child who has min dn is the successor ( node->turn==opposite(rootTurn) && successor->dn!=node->dn ) ) { if( node->virtualChildren.size() == 0 ) err(true, "proofNumberSearch(): can't find any successor at the node"); successor = new pnsNode(node, node->virtualChildren.back() ); node->actualChildren.push_back(successor); node->virtualChildren.pop_back(); } #ifdef PNSTEST safePrint(paper, "=> %d,(%d,%d),<%d,%d> ", opposite(node->turn), node->x, node->y, node->pn, node->dn); #endif return proofNumberSearch(successor, rootTurn, runTSS, paper); }
size_t parsePdfObj( size_t startPos, uint8_t *buf, size_t endPos, int dataType, struct pdfObject *curObjPtr ) { size_t curPos = startPos, bufOffset = 0, sPos; uint8_t tmpByte = 0, status = 0, *destBuf; int offset = 0, objNum = 0, objRev = 0, count = 0, getNum = 0, i; char tmpStr[1024]; char tmpBuf[4096]; struct pdfObject *tmpObjPtr; /* * parse this object */ if ( config->verbose ) printf( ">> %lu/%lu [%s]\n", startPos, endPos, typeStrings[dataType] ); /* * loop until we are at the end */ while ( curPos < endPos ) { if ( dataType EQ PDF_TYPE_NONE ) { #ifdef DEBUG if ( config->debug >= 5 ) hexDump( curPos, buf+curPos, 64 ); #endif if ( buf[curPos] EQ ' ' | buf[curPos] EQ '\r' | buf[curPos] EQ '\n' | buf[curPos] EQ '\t' ) { /* white space */ curPos++; } else if ( buf[curPos] EQ '<' ) { if ( buf[curPos+1] EQ '<' ) { /* dictionary */ curPos+=2; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_DICTIONARY; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_DICTIONARY, curObjPtr ); } else { /* hex string */ curPos++; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_HEXSTRING; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_HEXSTRING, curObjPtr ); } } else if ( buf[curPos] EQ '(' ) { /* string */ curPos++; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_STRING; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_STRING, curObjPtr ); } else if ( buf[curPos] EQ '/' ) { /* label */ curPos++; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_NAME; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NAME, curObjPtr ); } else if ( buf[curPos] EQ '[' ) { /* array */ curPos++; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_ARRAY; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_ARRAY, curObjPtr ); } else if ( sscanf( buf+curPos, "%d %d %n%s", &objNum, &objRev, &offset, tmpStr ) EQ 3 ) { /* named object */ if ( strncmp( tmpStr, "obj", 3 ) EQ 0 ) { printf( "Object: %d %d\n", objNum, objRev ); curPos += ( offset + 3 ); if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_OBJECT; curObjPtr->num = objNum; curObjPtr->gen = objRev; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_OBJECT, curObjPtr ); } else if ( tmpStr[0] EQ 'R' ) { printf( "ObjRef: %d %d\n", objNum, objRev ); curPos += ( offset + 1 ); if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_REFERENCE; curObjPtr->num = objNum; curObjPtr->gen = objRev; curObjPtr = curObjPtr->parent; /* once we have loaded all objects, we will link all references to their real objects */ } else { if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_INTNUM; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_INTNUM, curObjPtr ); } } else if ( isdigit( buf[curPos] ) || ( buf[curPos] EQ '-' ) || ( buf[curPos] EQ '+' ) ) { /* number */ if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_INTNUM; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_INTNUM, curObjPtr ); } else if ( ( buf[curPos] EQ 't' ) || ( buf[curPos] EQ 'f' ) ) { /* boolean number */ if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_BOOL; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_BOOL, curObjPtr ); } else if ( buf[curPos] EQ '%' ) { /* comment */ curPos++; /* check if this is EOF */ if ( strncmp( buf+curPos, "%EOF\n", 5 ) EQ 0 ) { curPos += 5; printf( "EOF\n" ); curObjPtr->type = PDF_TYPE_EOF; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_EOF, curObjPtr ); } else { if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_COMMENT; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_COMMENT, curObjPtr ); } } else if ( strncmp( buf+curPos, "stream", 6 ) EQ 0 ) { /* stream */ curPos += 6; if ( buf[curPos] EQ '\r' ) curPos++; if ( buf[curPos] EQ '\n' ) curPos++; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_STREAM; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_STREAM, curObjPtr ); } else if ( strncmp( buf+curPos, "obj", 3 ) EQ 0 ) { /* object */ curPos += 3; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_OBJECT; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_OBJECT, curObjPtr ); } else if ( strncmp( buf+curPos, "xref", 4 ) EQ 0 ) { /* start of footer */ curPos += 4; if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) { return FAILED; } curObjPtr->type = PDF_TYPE_FOOTER; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_FOOTER, curObjPtr ); } else if ( strncmp( buf+curPos, "startxref", 9 ) EQ 0 ) { curPos += 9; curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr ); } else if ( strncmp( buf+curPos, "endobj", 6 ) EQ 0 ) { return( curPos ); } else if ( buf[curPos] EQ ']' ) { return( curPos ); } else if ( strncmp( buf+curPos, ">>", 2 ) EQ 0 ) { return( curPos ); } else if ( buf[curPos] EQ '>' ) { return( curPos ); } else { if ( isprint( buf[curPos] ) ) printf( "%c", buf[curPos] ); else printf( "." ); curPos++; } } else if ( dataType EQ PDF_TYPE_EOF ) { /* all data after EOF is suspect */ if ( config->write ) { writeStream( curPos, buf+curPos, endPos - curPos ); } else hexDump( curPos, buf+curPos, endPos - curPos ); curPos = endPos; } else if ( dataType EQ PDF_TYPE_REALNUM ) { /* 3.4 = realNum */ sPos = curPos; if ( ( buf[curPos] EQ '-' ) || ( buf[curPos] EQ '+' ) ) { tmpStr[curPos-sPos] = buf[curPos]; curPos++; } while( isdigit( buf[curPos] ) || buf[curPos] EQ '.' ) { tmpStr[curPos-sPos] = buf[curPos]; curPos++; } tmpStr[curPos-sPos] = '\0'; printf( "Real Number: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_INTNUM ) { /* 343 = intNum */ sPos = curPos; if ( ( buf[curPos] EQ '-' ) || ( buf[curPos] EQ '+' ) ) curPos++; while( ( isdigit( buf[curPos] ) ) || ( buf[curPos] EQ '.' ) ) { if ( buf[curPos] EQ '.' ) { curObjPtr->type = PDF_TYPE_REALNUM; return parsePdfObj( sPos, buf, endPos, PDF_TYPE_REALNUM, curObjPtr ); } curPos++; } printf( "Integer: %d\n", atoi( buf+sPos ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_BOOL ) { /* true | false = bool */ if ( strncmp( buf+curPos, "true", 4 ) EQ 0 ) { /* true */ printf( "Boolean: true\n" ); curPos += 4; } else if ( strncmp( buf+curPos, "false", 5 ) EQ 0 ) { /* false */ printf( "Boolean: false\n" ); curPos += 5; } else curPos++; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_EOL ) { /* \n\r | \n | \n\r\n\r = EOL */ while( ( buf[curPos] EQ '\n' ) || ( buf[curPos] EQ '\r' ) ) { curPos++; } if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_COMMENT ) { /* % ... EOL = comment */ sPos = curPos; while( ( buf[curPos] != '\r' ) && ( buf[curPos] != '\n' ) ) { tmpStr[curPos-sPos] = buf[curPos]; curPos++; } tmpStr[curPos-sPos] = '\0'; printf( "Comment: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_NAME ) { /* / ... = name */ sPos = curPos; while( ( buf[curPos] != '\r' ) && ( buf[curPos] != '\n' ) && ( buf[curPos] != ' ' ) && ( buf[curPos] != '[' ) && ( buf[curPos] != '<' ) && ( buf[curPos] != '/' ) && ( buf[curPos] != '(' ) && ( buf[curPos] != '>' ) && ( buf[curPos] != ']' ) && ( buf[curPos] != ')' ) ) { /* process label */ tmpStr[curPos-sPos] = buf[curPos]; curPos++; } tmpStr[curPos-sPos] = '\0'; printf( "Name: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_STRING ) { /* ( ... ) = literalString */ /* XXX add octal notation '\000' */ /* XXX handle escaped characters */ while( buf[curPos] EQ ' ' ) { curPos++; } sPos = curPos; if ( strncmp( buf+curPos, "254 255", 7 ) EQ 0 ) { curObjPtr->type = PDF_TYPE_UTFSTRING; return parsePdfObj( curPos, buf, endPos, PDF_TYPE_UTFSTRING, curObjPtr ); } else if ( ( buf[curPos] EQ 'D' ) && ( buf[curPos+1] EQ ':' ) ) { curObjPtr->type = PDF_TYPE_DATESTRING; return parsePdfObj( curPos, buf, endPos, PDF_TYPE_DATESTRING, curObjPtr ); } while( buf[curPos] != ')' ) { tmpStr[curPos-sPos] = buf[curPos]; curPos++; } tmpStr[curPos-sPos] = '\0'; printf( "String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos + 1 ); } else if ( dataType EQ PDF_TYPE_UTFSTRING ) { /* ( 254 255 ... ) = utf encoded literal string */ while( sscanf( buf+curPos, "%u%n", (unsigned int *)&tmpByte, &offset ) EQ 1 ) { curPos += offset; if ( buf[curPos] EQ ' ' ) { curPos++; } } while( buf[curPos] != ')' ) { curPos++; } curPos++; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_DATESTRING ) { sPos = curPos; /* (D:YYYYMMDDHHmmSSOHH'mm') = date encoded literal string */ while( buf[curPos] != ')' ) { tmpStr[curPos-sPos] = buf[curPos]; curPos++; } curPos++; tmpStr[curPos-sPos] = '\0'; printf( "Date String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_HEXSTRING ) { /* < ... > = hexString */ count = 0; sPos = curPos; while( buf[curPos] != '>' ) { if ( isxdigit( buf[curPos] ) ) tmpStr[count++] = buf[curPos]; curPos++; } /* append a zero is the string length is odd */ if ( !( count % 2 ) EQ 0 ) { tmpStr[count++] = '0'; } tmpStr[count] = '\0'; curPos++; printf( "HEX String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); for( i = 0, offset = 0; i < count; i += 2 ) { tmpStr[offset++] = xtoi( tmpStr+i, 2 ); } hexDump( 0, tmpStr, offset ); printf( "HEX String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) ); if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_UTFHEXSTRING ) { /* < fe ff ... > = utf encoded hex string */ sPos = curPos; } else if ( dataType EQ PDF_TYPE_ARRAY ) { /* [ ... ] = array NOTE can be an array of any n objects */ while( buf[curPos] != ']' ) { curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr ); } curPos++; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_DICTIONARY ) { /* << /Kids [ 1 0 R 1 0 R ] = name tree */ /* /Names [ (key1) 1 0 R (key2) 2 0 R ] */ /* /Limits [ (firstKey) (lastKey) ] */ /* << name ... >> = dictionary where key is a name and value can be any object */ /* XXX organize into name, value pairs */ while( strncmp( buf+curPos, ">>", 2 ) != 0 ) { curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr ); } curPos += 2; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_OBJECT ) { /* 3 0 obj ... endobj = turns any object into an indirect (referencable) object */ /* 3 = objNum, 0 = objRev */ while ( strncmp( buf+curPos, "endobj", 6 ) != 0 ) { curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr ); } curPos += 6; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[PDF_TYPE_OBJECT] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_STREAM ) { /* XXX add code to associate the stream dictionary with the stream data */ /* << ... >>EOLstream\n\r or \r ... \n\r endstream = stream */ sPos = curPos; while( strncmp( buf+curPos, "endstream", 9 ) != 0 ) { curPos++; } printf( "Stream: %lu bytes\n", curPos - sPos ); /* allocate buffer for decompressed stream */ if ( ( destBuf = XMALLOC( ( curPos - sPos ) * 4 ) ) EQ NULL ) { fprintf( stderr, "ERR - Unable to allocate memory for stream\n" ); exit( 1 ); } XMEMSET( destBuf, 0, ( curPos-sPos ) * 4 ); /* decompress the stream */ z_stream zstrm; XMEMSET( &zstrm, 0, sizeof(zstrm) ); zstrm.avail_in = curPos-sPos; zstrm.avail_out = ( curPos-sPos ) * 4; zstrm.next_in = buf+sPos; zstrm.next_out = destBuf; int rsti = inflateInit(&zstrm); if (rsti EQ Z_OK) { int rst2 = inflate (&zstrm, Z_FINISH); if (rst2 >= 0) { if ( config->write ) { writeStream( sPos, destBuf, zstrm.total_out ); } else hexDump( 0, destBuf, zstrm.total_out ); } else { printf( "Stream did not decompress\n" ); if ( config->write ) { writeStream( sPos, buf+sPos, curPos-sPos ); } else hexDump( sPos, buf+sPos, curPos-sPos ); } } XFREE( destBuf ); curPos += 9; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } else if ( dataType EQ PDF_TYPE_HEADER ) { /* %PDF-1.6EOL%nnnnEOL = file header where each n is > 128 to make file look binary */ } else if ( dataType EQ PDF_TYPE_FOOTER ) { /* xref ... trailer ... startxref ... %%EOF = document footer */ /* XXX making an asumption, big mistake */ /* 0 271 */ /* 0000000000 65535 f */ /* 0000000015 00000 n */ /* found the xref, now look for the trailer, startxref and finally the EOF */ fprintf( stderr, "PDF Footer\n" ); /* XXX need to parse xref table, may be multiple tables in the file */ if ( strncmp( buf+curPos, "trailer", 7 ) EQ 0 ) { printf( "trailer\n" ); curPos += 7; } else curPos++; if ( config->verbose ) printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] ); return( curPos ); } } return( curPos ); }