Remove code that handled dutch items, old page formats, high bidder email, all bidder names (not available anymore), saving deleted listing ids in the XML file, large swaths of dead and/or obsolete code, and all the DB Time Queue code.
Abstracted the XMLElement code out to an interface, which XMLSerialize now uses, avoiding a circular dependency/tangle.
Made all my email addresses point to the same address, NOT at SourceForge anymore.
- A jbidwatcher/trunk/src/com/jbidwatcher/util/xml/XMLInterface.java
- M jbidwatcher/trunk/TODO view
- M jbidwatcher/trunk/ebay_co_uk.properties view
- M jbidwatcher/trunk/ebay_com.properties view
- M jbidwatcher/trunk/jbidwatcher.properties view
- M jbidwatcher/trunk/src/com/jbidwatcher/UpdaterEntry.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/Upgrader.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/app/JBidWatch.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/app/MacFriendlyFrame.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/AuctionActionImpl.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/AuctionEntry.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/AuctionInfo.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/AuctionServerInterface.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/AuctionSnipe.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/Auctions.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/Bidder.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/EntryInterface.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/Resolver.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/Snipe.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/SpecificAuction.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/event/EventLogger.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/server/AuctionServer.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/server/AuctionServerManager.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/server/ebay/ebayAuction.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/server/ebay/ebayBidder.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/server/ebay/ebayLoginManager.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/auction/server/ebay/ebayServer.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/my/MyJBidwatcher.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/ui/AuctionListHolder.java view
- M jbidwatcher/trunk/src/com/jbidwatcher/ui/AuctionsManager.java view
| 884 | 1000 | |
|---|---|---|
| 99 | 99 | THIS ALSO CAN BE VERY, VERY EXPENSIVE! |
| 100 | 100 | |
| 101 | 101 | ---------------------------------------------------------------------- |
| 102 | * After payment, dutch auctions subtract out from the 'available' list, and the user seems to no longer have won the listing. | |
| 103 | ||
| 104 | 102 | * Add to watch list: |
| 105 | 103 | http://cgi1.ebay.com/ws/eBayISAPI.dll?ViewItemMakeTrack&item=6047388445 |
| 106 | 104 | http://cgi1.ebay.com/ws/eBayISAPI.dll?ViewItemMakeTrack&item=5104953681 |
| 994 | 1000 | |
|---|---|---|
| 68 | 68 | view.original.listing=View the original listing |
| 69 | 69 | |
| 70 | 70 | ebayServer.bidHost=offer.ebay.co.uk |
| 71 | ebayServer.dutchRequestHost=offer.ebay.co.uk | |
| 72 | 71 | ebayServer.signInPage=https://signin.ebay.co.uk/ws2/eBayISAPI.dll?SignIn |
| 73 | 72 | ebayServer.bidderNamesHost=cgi6.ebay.co.uk |
| 74 | 73 | ebayServer.buyRequest=http://offer.ebay.co.uk/ws/eBayISAPI.dll?MfcISAPICommand=BinConfirm&fb=1&co_partnerid= |
| 994 | 1000 | |
|---|---|---|
| 57 | 57 | ebayServer.warningPage=(?i)(Buying.Reminder|Safe.Trading.Tips) |
| 58 | 58 | ebayServer.feedback=Feedback: |
| 59 | 59 | ebayServer.viewHost=cgi.ebay.com |
| 60 | ebayServer.detectionHost=^(cgi\\.ebay\\.|cgi\\.tw\\.ebay\\.|cgi\\.es\\.ebay\\.).*$ | |
| 61 | 60 | your.information.has.been.verified=(?ms).*Your information has been verified.* |
| 62 | 61 | mature.audiences.accepted=(?ms).*You may now view these pages.* |
| 63 | 62 | mature.audiences.disallowed.outside.the.us=(?ms).*not to allow access to the Mature Audiences category outside the US.* |
| --- | --- | |
| 70 | 69 | view.original.listing=View the original listing |
| 71 | 70 | |
| 72 | 71 | ebayServer.bidHost=offer.ebay.com |
| 73 | ebayServer.dutchRequestHost=offer.ebay.com | |
| 74 | 72 | ebayServer.signInPage=https://signin.ebay.com/ws2/eBayISAPI.dll?SignIn |
| 75 | 73 | ebayServer.bidderNamesHost=cgi6.ebay.com |
| 76 | 74 | ebayServer.buyRequest=http://offer.ebay.com/ws/eBayISAPI.dll?MfcISAPICommand=BinConfirm&fb=1&co_partnerid= |
| 969 | 1000 | |
|---|---|---|
| 2 | 2 | ebayServer.protocol=http:// |
| 3 | 3 | ebayServer.file=/ws/eBayISAPI.dll |
| 4 | 4 | ebayServer.V3file=/ws/eBayISAPI.dll |
| 5 | ebayServer.V3WS3File=/ws3/eBayISAPI.dll | |
| 6 | 5 | ebayServer.viewCmd=ViewItem& |
| 7 | 6 | ebayServer.viewCGI=item= |
| 8 | ebayServer.viewDutch=?ViewBidsDutchHighBidder&item= | |
| 9 | 7 | ebayServer.searchURL2=&srchdesc=y&category0=&ebaytag1=ebayctry&ebaytag1code=0&SortProperty=MetaEndSort&SortOrder=%5Ba%5D&st=0&maxRecordsPerPage=100 |
| 10 | 8 | ebayServer.searchURLNoDesc=&srchdesc=n&category0=&ebaytag1=ebayctry&ebaytag1code=0&SortProperty=MetaEndSort&SortOrder=%5Ba%5D&st=0&maxRecordsPerPage=100 |
| 11 | 9 | ebayServer.bidCmd=MfcISAPICommand=MakeBid |
| 959 | 1000 | |
|---|---|---|
| 9 | 9 | import com.jbidwatcher.util.xml.XMLParseException; |
| 10 | 10 | import com.jbidwatcher.util.xml.XMLElement; |
| 11 | 11 | import com.jbidwatcher.util.xml.XMLSerializeSimple; |
| 12 | import com.jbidwatcher.util.xml.XMLInterface; | |
| 12 | 13 | import com.jbidwatcher.ui.util.OptionUI; |
| 13 | 14 | import com.jbidwatcher.util.http.Http; |
| 14 | 15 | import com.jbidwatcher.util.Constants; |
| --- | --- | |
| 24 | 25 | protected String _description = ""; // Optional |
| 25 | 26 | protected String _url = ""; |
| 26 | 27 | protected boolean _valid; |
| 27 | protected boolean _hasConfigChanges; | |
| 28 | protected ArrayList<XMLElement> configChanges; | |
| 28 | protected ArrayList<XMLInterface> mConfigChanges; | |
| 29 | 29 | |
| 30 | // For creating, then filling in later, especially when loading from a | |
| 31 | // file, instead of remotely. | |
| 32 | public UpdaterEntry() { } | |
| 33 | ||
| 34 | 30 | public UpdaterEntry(String packageName, String updateFrom) { |
| 35 | 31 | StringBuffer loadedUpdate; |
| 36 | 32 | |
| --- | --- | |
| 98 | 94 | if(valid) { |
| 99 | 95 | String strStamp = curElement.getProperty("STAMP"); |
| 100 | 96 | if(strStamp == null) { |
| 101 | if(configChanges == null) configChanges = new ArrayList<XMLElement>(5); | |
| 102 | configChanges.add(curElement); | |
| 97 | if(mConfigChanges == null) mConfigChanges = new ArrayList<XMLInterface>(5); | |
| 98 | mConfigChanges.add(curElement); | |
| 103 | 99 | } else { |
| 104 | 100 | long stamp = Long.parseLong(strStamp); |
| 105 | 101 | long last = Long.parseLong(JConfig.queryConfiguration("updates.lastConfig", "0")); |
| 106 | 102 | if(stamp > last) { |
| 107 | if(configChanges == null) configChanges = new ArrayList<XMLElement>(5); | |
| 108 | configChanges.add(curElement); | |
| 103 | if(mConfigChanges == null) mConfigChanges = new ArrayList<XMLInterface>(5); | |
| 104 | mConfigChanges.add(curElement); | |
| 109 | 105 | } |
| 110 | 106 | } |
| 111 | 107 | } |
| --- | --- | |
| 136 | 132 | } |
| 137 | 133 | |
| 138 | 134 | public boolean hasConfigurationUpdates() { |
| 139 | return configChanges != null; | |
| 135 | return mConfigChanges != null; | |
| 140 | 136 | } |
| 141 | 137 | |
| 142 | 138 | public void applyConfigurationUpdates() { |
| --- | --- | |
| 144 | 140 | boolean cfgChanged = false; |
| 145 | 141 | long lastStamp = Long.parseLong(JConfig.queryConfiguration("updates.lastConfig", "0")); |
| 146 | 142 | |
| 147 | for (XMLElement cfg : configChanges) { | |
| 143 | for (XMLInterface cfg : mConfigChanges) { | |
| 148 | 144 | String type = cfg.getProperty("TYPE", "config"); |
| 149 | 145 | if (type.equals("message")) { |
| 150 | 146 | if (alert == null) { |
| 844 | 1000 | |
|---|---|---|
| 57 | 57 | return schemaInfo.getDB(); |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | private static boolean tableExists(Database db, Statement s, String tableName) throws SQLException { | |
| 60 | private static boolean tableExists(Statement s, String tableName) throws SQLException { | |
| 61 | 61 | ResultSet rs = s.getConnection().getMetaData().getTables(null, null, tableName, null); |
| 62 | 62 | boolean result = rs.next(); |
| 63 | 63 | rs.close(); |
| --- | --- | |
| 72 | 72 | */ |
| 73 | 73 | Statement mS = db.getStatement(); |
| 74 | 74 | |
| 75 | boolean schema_info_exists = tableExists(db, mS, "schema_info"); | |
| 76 | if(!schema_info_exists) schema_info_exists = tableExists(db, mS, "SCHEMA_INFO"); | |
| 75 | boolean schema_info_exists = tableExists(mS, "schema_info"); | |
| 76 | if(!schema_info_exists) schema_info_exists = tableExists(mS, "SCHEMA_INFO"); | |
| 77 | 77 | |
| 78 | 78 | if(!schema_info_exists) { |
| 79 | 79 | runFile(db, mS, "/jbidwatcher.sql"); |
| 908 | 1000 | |
|---|---|---|
| 42 | 42 | |
| 43 | 43 | /** |
| 44 | 44 | * @file JBidWatch.java |
| 45 | * @author Morgan Schweers <cyberfox@users.sourceforge.net> | |
| 45 | * @author Morgan Schweers <cyberfox@jbidwatcher.com> | |
| 46 | 46 | * @date Fri Oct 11 17:54:21 2002 |
| 47 | 47 | * |
| 48 | 48 | * @brief The startup class, that prepares the UI, and starts all the |
| 952 | 1000 | |
|---|---|---|
| 37 | 37 | /** |
| 38 | 38 | * @brief Constructs a new window frame, with all the sorted tables, |
| 39 | 39 | * scroll bars, drag and drop targets, menu & header bar, and status |
| 40 | * line. | |
| 40 | * line. Returns a completed frame, suitable for displaying as the primary UI of the program. | |
| 41 | 41 | * |
| 42 | 42 | * @param title - The frame title. |
| 43 | 43 | * @param myFrameAdapter - The adapter to listen to mouse events. |
| 44 | 44 | * @param iconURL - The URL of the icon to associate with the frame. |
| 45 | 45 | * @param tabManager - The Tab Manager to display within the frame. |
| 46 | * | |
| 47 | * @return A completed frame, suitable for displaying as the primary UI of the program. | |
| 48 | 46 | */ |
| 49 | 47 | public MacFriendlyFrame(String title, JMouseAdapter myFrameAdapter, URL iconURL, JTabManager tabManager) { |
| 50 | 48 | super(title); |
| 984 | 1000 | |
|---|---|---|
| 65 | 65 | public int getResult() { return mResult; } |
| 66 | 66 | public boolean isSuccessful() { |
| 67 | 67 | return (mResult == AuctionServerInterface.BID_WINNING || |
| 68 | mResult == AuctionServerInterface.BID_DUTCH_CONFIRMED || | |
| 69 | 68 | mResult == AuctionServerInterface.BID_SELFWIN); |
| 70 | 69 | } |
| 71 | 70 | |
| --- | --- | |
| 82 | 81 | bidResultString = "Bidding apparently failed, as the auction cannot be bid on anymore (probably ended)!"; |
| 83 | 82 | JConfig.increment("stats.bid.too_late"); |
| 84 | 83 | break; |
| 85 | case com.jbidwatcher.auction.AuctionServerInterface.BID_DUTCH_CONFIRMED: | |
| 86 | bidResultString = "Your dutch bid was confirmed, and you are in the list of high bidders!"; | |
| 87 | JConfig.increment("stats.bid.success"); | |
| 88 | break; | |
| 89 | 84 | case AuctionServerInterface.BID_ERROR_BANNED: |
| 90 | 85 | bidResultString = "Your bid failed, as you are disallowed from bidding on this seller's items."; |
| 91 | 86 | JConfig.increment("stats.bid.banned"); |
| 997 | 1000 | |
|---|---|---|
| 15 | 15 | import com.jbidwatcher.util.db.ActiveRecord; |
| 16 | 16 | import com.jbidwatcher.util.db.Table; |
| 17 | 17 | import com.jbidwatcher.util.xml.XMLElement; |
| 18 | import com.jbidwatcher.util.xml.XMLInterface; | |
| 18 | 19 | |
| 19 | import java.io.FileNotFoundException; | |
| 20 | 20 | import java.io.File; |
| 21 | 21 | import java.text.MessageFormat; |
| 22 | 22 | import java.util.*; |
| --- | --- | |
| 84 | 84 | return mSnipe; |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | public static class AuctionComparator implements Comparator<AuctionEntry> | |
| 88 | { | |
| 89 | /** | |
| 90 | * @param o1 - The first auction entry. | |
| 91 | * @param o2 - The second auction entry. | |
| 92 | * @return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2. | |
| 93 | * @brief Compare two auction objects for ordering by end-date. | |
| 94 | */ | |
| 95 | public int compare(AuctionEntry o1, AuctionEntry o2) { | |
| 96 | if (o1 == null && o2 == null) return 0; | |
| 97 | if (o1 == null) return -1; | |
| 98 | if (o2 == null) return 1; | |
| 99 | ||
| 100 | int result = o1.getEndDate().compareTo(o2.getEndDate()); | |
| 101 | if (result == 0) { | |
| 102 | result = o1.compareTo(o2); | |
| 103 | } | |
| 104 | return result; | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | 87 | /** All the auction-independant information like high bidder's name, |
| 109 | 88 | * seller's name, etc... This is directly queried when this object |
| 110 | 89 | * is queried about any of those fields. |
| --- | --- | |
| 161 | 140 | private Currency mCancelSnipeBid = null; |
| 162 | 141 | |
| 163 | 142 | /** |
| 164 | * How many items are to be sniped on, but were cancelled? | |
| 165 | */ | |
| 166 | private int mCancelSnipeQuant =1; | |
| 167 | ||
| 168 | /** | |
| 169 | 143 | * What AuctionServer is responsible for handling this |
| 170 | 144 | * AuctionEntry's actions? |
| 171 | 145 | */ |
| --- | --- | |
| 607 | 581 | } |
| 608 | 582 | |
| 609 | 583 | /** |
| 610 | * @brief Determine how long before the auction-end is the default | |
| 611 | * snipe set to fire? | |
| 612 | * | |
| 613 | * @return The number of milliseconds prior to auction end that a | |
| 614 | * snipe should fire. | |
| 615 | */ | |
| 616 | public static long getDefaultSnipeTime() { | |
| 617 | sDefaultSnipeAt = getGlobalSnipeTime(); | |
| 618 | return sDefaultSnipeAt; | |
| 619 | } | |
| 620 | ||
| 621 | /** | |
| 622 | 584 | * @brief Set how long before auctions are complete to fire snipes |
| 623 | 585 | * for any auction using the default snipe timer. |
| 624 | 586 | * |
| --- | --- | |
| 662 | 624 | public void updateHighBid() { |
| 663 | 625 | int numBidders = getNumBidders(); |
| 664 | 626 | |
| 665 | if (numBidders > 0 /* && isOutbid() */) { | |
| 627 | if (numBidders > 0 || isFixed()) { | |
| 666 | 628 | getServer().updateHighBid(this); |
| 667 | 629 | } |
| 668 | 630 | } |
| --- | --- | |
| 701 | 663 | } |
| 702 | 664 | |
| 703 | 665 | /** |
| 704 | * @brief Determine if we're a high bidder on a multi-item ('dutch') | |
| 705 | * auction. | |
| 706 | */ | |
| 707 | public void checkDutchHighBidder() { | |
| 708 | setWinning(getServer().isHighDutch(this)); | |
| 709 | } | |
| 710 | ||
| 711 | /** | |
| 712 | 666 | * @brief Set the flags if the current user is the seller in this auction. |
| 713 | 667 | */ |
| 714 | 668 | private void checkSeller() { |
| --- | --- | |
| 1017 | 971 | * |
| 1018 | 972 | * @param inXML - The XMLElement that contains the items to load. |
| 1019 | 973 | */ |
| 1020 | public void fromXML(XMLElement inXML) { | |
| 974 | public void fromXML(XMLInterface inXML) { | |
| 1021 | 975 | String inID = inXML.getProperty("ID", null); |
| 1022 | 976 | if(inID != null) { |
| 1023 | 977 | mAuction = new AuctionInfo(); |
| --- | --- | |
| 1082 | 1036 | public Currency getCancelledSnipe() { return mCancelSnipeBid; } |
| 1083 | 1037 | |
| 1084 | 1038 | /** |
| 1085 | * @brief Return the quantity that the snipe bid was for, before it | |
| 1086 | * was cancelled. | |
| 1087 | * | |
| 1088 | * @return - A number of items (for dutch only) that were to be bid on. | |
| 1089 | */ | |
| 1090 | public int getCancelledSnipeQuantity() { return mCancelSnipeQuant; } | |
| 1091 | ||
| 1092 | /** | |
| 1093 | 1039 | * Cancel the snipe and clear the multisnipe setting. This is used for |
| 1094 | 1040 | * user-driven snipe cancellations, and errors like the listing going away. |
| 1095 | 1041 | * |
| --- | --- | |
| 1107 | 1053 | setLastStatus("Cancelling snipe."); |
| 1108 | 1054 | if(after_end) { |
| 1109 | 1055 | mCancelSnipeBid = getSnipe().getAmount(); |
| 1110 | mCancelSnipeQuant = getSnipe().getQuantity(); | |
| 1111 | 1056 | } |
| 1112 | 1057 | } |
| 1113 | 1058 | } |
| --- | --- | |
| 1154 | 1099 | try { |
| 1155 | 1100 | updateHighBid(); |
| 1156 | 1101 | checkHighBidder(); |
| 1157 | if(isDutch()) checkDutchHighBidder(); | |
| 1158 | 1102 | } catch(Exception e) { |
| 1159 | 1103 | JConfig.log().handleException("Unexpected exception during high bidder check.", e); |
| 1160 | 1104 | } |
| --- | --- | |
| 1232 | 1176 | getServer().setSnipe(this); |
| 1233 | 1177 | } |
| 1234 | 1178 | |
| 1235 | /** @brief Actually bid on a single item for a given price. | |
| 1236 | * | |
| 1237 | * Also called by the snipe() function, to actually bid. | |
| 1238 | * | |
| 1239 | * @param bid - The amount of money to bid on 1 of this item. | |
| 1240 | * | |
| 1241 | * @return The result of the bid attempt. | |
| 1242 | */ | |
| 1243 | public int bid(Currency bid) { | |
| 1244 | return( bid(bid, 1) ); | |
| 1245 | } | |
| 1246 | ||
| 1247 | 1179 | /** |
| 1248 | 1180 | * @brief Bid a given price on an arbitrary number of a particular item. |
| 1249 | 1181 | * |
| --- | --- | |
| 1633 | 1565 | |
| 1634 | 1566 | public String getSeller() { return getAuction().getSellerName(); } |
| 1635 | 1567 | public String getHighBidder() { return getAuction().getHighBidder(); } |
| 1636 | public String getHighBidderEmail() { return getAuction().getHighBidderEmail(); } | |
| 1637 | 1568 | public String getTitle() { return getAuction().getTitle(); } |
| 1638 | 1569 | |
| 1639 | 1570 | public Date getStartDate() { |
| --- | --- | |
| 1660 | 1591 | public boolean isReserveMet() { return getAuction().isReserveMet(); } |
| 1661 | 1592 | public boolean isPrivate() { return getAuction().isPrivate(); } |
| 1662 | 1593 | public boolean isFixed() { return getAuction().isFixedPrice(); } |
| 1663 | public boolean isOutbid() { return getAuction().isOutbid(); } | |
| 1664 | 1594 | |
| 1665 | 1595 | public StringBuffer getContent() { return getAuction().getContent(); } |
| 1666 | 1596 | public File getContentFile() { return getAuction().getContentFile(); } |
| --- | --- | |
| 1697 | 1627 | return ship != null && !ship.isNull(); |
| 1698 | 1628 | } |
| 1699 | 1629 | |
| 1700 | public String getURL() { | |
| 1701 | return getServer().getStringURLFromItem(getAuction().getIdentifier()); | |
| 1702 | } | |
| 1703 | ||
| 1704 | public StringBuffer getBody() throws FileNotFoundException { | |
| 1705 | return getServer().getAuction(StringTools.getURLFromString(getURL())); | |
| 1706 | } | |
| 1707 | ||
| 1708 | 1630 | /** |
| 1709 | 1631 | * Is the auction deleted on the server? |
| 1710 | 1632 | * |
| --- | --- | |
| 1934 | 1856 | public static final String newCol = "</td><td>"; |
| 1935 | 1857 | public static final String endRow = "</td></tr>"; |
| 1936 | 1858 | |
| 1859 | // TODO -- Extract this crap out to a EntryHTMLBuilder class, which gets instantiated with an AuctionEntry object. | |
| 1937 | 1860 | public String buildInfoHTML() { |
| 1938 | return buildInfoHTML(false, false); | |
| 1861 | return buildInfoHTML(false); | |
| 1939 | 1862 | } |
| 1940 | 1863 | |
| 1941 | public String buildInfoHTML(boolean finalize, boolean forRSS) { | |
| 1864 | public String buildInfoHTML(boolean forRSS) { | |
| 1942 | 1865 | String prompt = ""; |
| 1943 | if(finalize) prompt = "<html><body>"; | |
| 1944 | 1866 | |
| 1945 | 1867 | if(forRSS) { |
| 1946 | 1868 | prompt += "<b>" + StringTools.stripHigh(getTitle()) + "</b> (" + getIdentifier() + ")<br>"; |
| --- | --- | |
| 1953 | 1875 | if (forRSS) { |
| 1954 | 1876 | try { |
| 1955 | 1877 | InetAddress thisIp = InetAddress.getLocalHost(); |
| 1956 | prompt += newRow + "<img src=\"http://" + thisIp.getHostAddress() + ":" + JConfig.queryConfiguration("server.port", "9099") + "/" + getIdentifier() + ".jpg\">" + newCol + "<table>"; | |
| 1878 | prompt += newRow + "<img src=\"http://" + thisIp.getHostAddress() + ":" + JConfig.queryConfiguration("server.port", Constants.DEFAULT_SERVER_PORT_STRING) + "/" + getIdentifier() + ".jpg\">" + newCol + "<table>"; | |
| 1957 | 1879 | addedThumbnail = true; |
| 1958 | 1880 | } catch (UnknownHostException e) { |
| 1959 | 1881 | // Couldn't find THIS host?!? Perhaps that means we're not online? |
| --- | --- | |
| 1966 | 1888 | } |
| 1967 | 1889 | prompt = buildInfoBody(prompt, addedThumbnail); |
| 1968 | 1890 | |
| 1969 | if(finalize) { | |
| 1970 | prompt += "</html>"; | |
| 1971 | } | |
| 1972 | 1891 | return(prompt); |
| 1973 | 1892 | } |
| 1974 | 1893 | |
| --- | --- | |
| 2071 | 1990 | public static XMLElement retrieveAuctionXML(String identifier) { |
| 2072 | 1991 | AuctionEntry ae = AuctionEntry.construct(identifier); |
| 2073 | 1992 | if (ae != null) { |
| 2074 | if (ae.isDutch()) ae.checkDutchHighBidder(); | |
| 2075 | return ae.toXML(); | |
| 1993 | return ae.toXML(); // TODO -- Check high bidder (a separate request). | |
| 2076 | 1994 | } |
| 2077 | 1995 | |
| 2078 | 1996 | return null; |
| 997 | 1000 | |
|---|---|---|
| 73 | 73 | } |
| 74 | 74 | |
| 75 | 75 | protected Seller mSeller; |
| 76 | ||
| 77 | protected static final sun.misc.BASE64Decoder b64dec = new sun.misc.BASE64Decoder(); | |
| 78 | protected static final sun.misc.BASE64Encoder b64enc = new sun.misc.BASE64Encoder(); | |
| 79 | 76 | protected GZip mLoadedPage = null; |
| 80 | 77 | |
| 81 | 78 | /** |
| --- | --- | |
| 86 | 83 | setTranslationTable(mKeys); |
| 87 | 84 | } |
| 88 | 85 | |
| 89 | /** | |
| 90 | * @brief Construct a somewhat complete AuctionInfo object with all | |
| 91 | * the important values set. | |
| 92 | * | |
| 93 | * @param auctionTitle - The title of the auction. | |
| 94 | * @param auctionSeller - The seller's username for the auction. | |
| 95 | * @param auctionHighBidder - The current high bidder, if any. | |
| 96 | * @param auctionCurBid - The current/lowest/starting bid. | |
| 97 | * @param auctionStart - The start time for the auction (if available). | |
| 98 | * @param auctionEnd - The end time for the auction. | |
| 99 | * @param auctionBidCount - The number of bids that have been placed so far. | |
| 100 | */ | |
| 101 | protected AuctionInfo(String auctionTitle, String auctionSeller, String auctionHighBidder, | |
| 102 | Currency auctionCurBid, Date auctionStart, Date auctionEnd, int auctionBidCount) { | |
| 103 | setTranslationTable(mKeys); | |
| 104 | setTitle(auctionTitle.trim()); | |
| 105 | setHighBidder(auctionHighBidder.trim()); | |
| 106 | setSellerName(auctionSeller.trim()); | |
| 107 | ||
| 108 | setStart(auctionStart); | |
| 109 | setEnd(auctionEnd); | |
| 110 | ||
| 111 | setCurBid(auctionCurBid); | |
| 112 | setNumBids(auctionBidCount); | |
| 113 | } | |
| 114 | ||
| 115 | public Record getMap() { | |
| 116 | return getBacking(); | |
| 117 | } | |
| 118 | ||
| 119 | 86 | protected String[] infoTags = { "title", "seller", "highbidder", "bidcount", "start", "end", |
| 120 | 87 | "currently", "dutch", "reserve", "private", "content", |
| 121 | 88 | "shipping", "insurance", "buynow", "usprice", "fixed", "minimum", |
| --- | --- | |
| 407 | 374 | public String getIdentifier() { return getString("identifier"); } |
| 408 | 375 | public String getTitle() { return getString("title"); } |
| 409 | 376 | public String getHighBidder() { return getString("highBidder"); } |
| 410 | public String getHighBidderEmail() { return getString("highBidderEmail"); } | |
| 377 | // public String getHighBidderEmail() { return getString("highBidderEmail"); } | |
| 411 | 378 | public String getItemLocation() { return getString("itemLocation", ""); } |
| 412 | 379 | |
| 413 | 380 | public Currency getCurBid() { return getMonetary("curBid"); } |
| --- | --- | |
| 435 | 402 | protected boolean isPrivate() { return getBoolean("isPrivate"); } |
| 436 | 403 | protected boolean isFixedPrice() { return getBoolean("fixed_price"); } |
| 437 | 404 | boolean isReserveMet() { return getBoolean("reserveMet"); } |
| 438 | boolean isOutbid() { return getBoolean("outbid"); } | |
| 439 | 405 | protected boolean hasPaypal() { return getBoolean("paypal"); } |
| 440 | 406 | boolean hasThumb() { return getBoolean("has_thumbnail"); } |
| 441 | 407 | boolean isInsuranceOptional() { return getBoolean("insurance_optional", true); } |
| --- | --- | |
| 457 | 423 | refreshSeller(); |
| 458 | 424 | return mSeller; |
| 459 | 425 | } |
| 426 | ||
| 460 | 427 | public String getPositiveFeedbackPercentage() { |
| 461 | 428 | refreshSeller(); |
| 462 | 429 | if (mSeller != null) return mSeller.getPositivePercentage(); |
| --- | --- | |
| 493 | 460 | public void setIdentifier(String id) { setString("identifier", id); } |
| 494 | 461 | public void setHighBidder(String highBidder) { setString("highBidder", highBidder); } |
| 495 | 462 | protected void setTitle(String title) { setString("title", title); } |
| 496 | protected void setHighBidderEmail(String highBidderEmail) { setString("highBidderEmail", highBidderEmail); } | |
| 463 | // protected void setHighBidderEmail(String highBidderEmail) { setString("highBidderEmail", highBidderEmail); } | |
| 497 | 464 | protected void setItemLocation(String itemLocation) { setString("itemLocation", itemLocation); } |
| 498 | 465 | |
| 499 | 466 | protected void setInsuranceOptional(boolean insuranceOptional) { setBoolean("insuranceOptional", insuranceOptional); } |
| --- | --- | |
| 514 | 481 | protected void setQuantity(int quantity) { setInteger("quantity", quantity); } |
| 515 | 482 | protected void setNumBids(int numBids) { setInteger("numBids", numBids); } |
| 516 | 483 | |
| 517 | protected void setDutch(boolean dutch) { setBoolean("isDutch", dutch); } | |
| 518 | 484 | protected void setReserve(boolean isReserve) { setBoolean("isReserve", isReserve); } |
| 519 | 485 | protected void setPrivate(boolean isPrivate) { setBoolean("private", isPrivate); } |
| 520 | 486 | protected void setReserveMet(boolean reserveMet) { setBoolean("reserveMet", reserveMet); } |
| 962 | 1000 | |
|---|---|---|
| 19 | 19 | int BID_ERROR_OUTBID=3; |
| 20 | 20 | int BID_WINNING=4; |
| 21 | 21 | int BID_SELFWIN=5; |
| 22 | int BID_DUTCH_CONFIRMED=6; | |
| 22 | // int BID_DUTCH_CONFIRMED=6; -- This is obsolete. | |
| 23 | 23 | int BID_ERROR_MULTI=7; |
| 24 | 24 | int BID_ERROR_TOO_LOW=8; |
| 25 | 25 | int BID_ERROR_ENDED=9; |
| --- | --- | |
| 113 | 113 | |
| 114 | 114 | boolean isCurrentUser(String checkUser); |
| 115 | 115 | |
| 116 | boolean isHighDutch(EntryInterface entry); | |
| 117 | ||
| 118 | 116 | void updateHighBid(AuctionEntry eEntry); |
| 119 | 117 | |
| 120 | 118 | String stripId(String source); |
| 849 | 1000 | |
|---|---|---|
| 60 | 60 | return snipe; |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | public String saveDB() { | |
| 64 | return super.saveDB(); | |
| 65 | } | |
| 66 | ||
| 67 | 63 | private static Table sDB = null; |
| 68 | 64 | protected static String getTableName() { return "snipes"; } |
| 69 | 65 | |
| 985 | 1000 | |
|---|---|---|
| 11 | 11 | import com.jbidwatcher.util.Comparison; |
| 12 | 12 | import com.jbidwatcher.util.UpdateBlocker; |
| 13 | 13 | import com.jbidwatcher.util.Task; |
| 14 | import com.jbidwatcher.util.xml.XMLElement; | |
| 14 | import com.jbidwatcher.util.xml.XMLInterface; | |
| 15 | 15 | |
| 16 | 16 | /** |
| 17 | 17 | * This class shouldn't have a 'TableSorter', it should defer to some |
| --- | --- | |
| 25 | 25 | * class could build it's own atm and tablesorter. -- BUGBUG |
| 26 | 26 | */ |
| 27 | 27 | public class Auctions implements TimerHandler.WakeupProcess { |
| 28 | boolean _selling = false; | |
| 29 | 28 | boolean _complete = false; |
| 30 | 29 | // private volatile TableSorter _tSort; |
| 31 | 30 | private AuctionList mList; |
| --- | --- | |
| 43 | 42 | return _name; |
| 44 | 43 | } |
| 45 | 44 | |
| 46 | public void setSelling() { _selling = true; } | |
| 47 | public boolean isSelling() { return _selling; } | |
| 48 | 45 | public void setComplete() { _complete = true; } |
| 49 | 46 | public boolean isCompleted() { return _complete; } |
| 50 | 47 | |
| 51 | 48 | /** |
| 52 | * Search for an AuctionEntry in our tables, given it's identifier. | |
| 53 | * | |
| 54 | * @param whatIdentifier - The identifier to search for. | |
| 55 | * | |
| 56 | * @return - The AuctionEntry, if it's found, or null if none was found. | |
| 57 | */ | |
| 58 | public EntryInterface getEntry(final String whatIdentifier) { | |
| 59 | return mList.find(new Comparison() { | |
| 60 | public boolean match(Object o) { | |
| 61 | if (o instanceof EntryInterface) { | |
| 62 | EntryInterface ae = (EntryInterface) o; | |
| 63 | if (whatIdentifier.equals(ae.getIdentifier())) { | |
| 64 | return true; | |
| 65 | } | |
| 66 | } | |
| 67 | return false; | |
| 68 | } | |
| 69 | }); | |
| 70 | } | |
| 71 | ||
| 72 | /** | |
| 73 | 49 | * Add an AuctionEntry that has already been created, denying |
| 74 | 50 | * previously deleted items. |
| 75 | 51 | * |
| --- | --- | |
| 81 | 57 | return aeNew != null && !DeletedEntry.exists(aeNew.getIdentifier()); |
| 82 | 58 | } |
| 83 | 59 | |
| 84 | /** | |
| 85 | * Verify that the auction provided exists. | |
| 86 | * | |
| 87 | * @param auctionId - The auction ID to search for. | |
| 88 | * | |
| 89 | * @return - true if the auction is in the list, false otherwise. | |
| 90 | */ | |
| 91 | public boolean verifyEntry(String auctionId) { | |
| 92 | EntryInterface ae = getEntry(auctionId); | |
| 93 | ||
| 94 | return (ae != null); | |
| 95 | } | |
| 96 | ||
| 97 | 60 | /** |
| 98 | * Verify that the auction provided exists. | |
| 99 | * | |
| 100 | * @param ae - The auction entry to search for. | |
| 101 | * | |
| 102 | * @return - true if the auction is in the list, false otherwise. | |
| 103 | */ | |
| 104 | public boolean verifyEntry(final EntryInterface ae) { | |
| 105 | Object result = mList.find(new Comparison() { | |
| 106 | public boolean match(Object o) { //noinspection ObjectEquality | |
| 107 | return o == ae; } | |
| 108 | }); | |
| 109 | return result != null; | |
| 110 | } | |
| 111 | ||
| 112 | /** | |
| 113 | 61 | * For display during updates, we want the title and potentially the |
| 114 | 62 | * comment, to display all that in the status bar while we're |
| 115 | 63 | * updating. |
| --- | --- | |
| 135 | 83 | * completed), and then let the user know we finished. |
| 136 | 84 | * |
| 137 | 85 | * @param ae - The auction to update. |
| 138 | * @return - true if the auction was moved to another category, false otherwise. | |
| 139 | 86 | */ |
| 140 | private boolean doUpdate(AuctionEntry ae) { | |
| 87 | private void doUpdate(AuctionEntry ae) { | |
| 141 | 88 | String titleWithComment = getTitleAndComment(ae); |
| 142 | 89 | |
| 143 | 90 | if(!ae.isComplete() || ae.isUpdateForced()) { |
| --- | --- | |
| 145 | 92 | ae.setUpdating(); |
| 146 | 93 | MQFactory.getConcrete("redraw").enqueue(ae.getIdentifier()); |
| 147 | 94 | Thread.yield(); |
| 148 | XMLElement before = ae.toXML(); | |
| 95 | XMLInterface before = ae.toXML(); | |
| 149 | 96 | ae.update(); |
| 150 | XMLElement after = ae.toXML(); | |
| 97 | XMLInterface after = ae.toXML(); | |
| 151 | 98 | ae.clearUpdating(); |
| 152 | 99 | if (!(after.toString().equals(before.toString()))) { |
| 153 | 100 | MQFactory.getConcrete("upload").enqueue(ae.getIdentifier()); |
| --- | --- | |
| 157 | 104 | MQFactory.getConcrete("redraw").enqueue(ae.getIdentifier()); |
| 158 | 105 | MQFactory.getConcrete("Swing").enqueue("Done updating " + Auctions.getTitleAndComment(ae)); |
| 159 | 106 | } |
| 160 | return false; | |
| 161 | 107 | } |
| 162 | 108 | |
| 163 | 109 | /** |
| --- | --- | |
| 171 | 117 | */ |
| 172 | 118 | private boolean doNextUpdate() { |
| 173 | 119 | AuctionEntry result = mList.find(new Comparison() { |
| 174 | public boolean match(Object o) { if(o == null) return false; return ((AuctionEntry) o).checkUpdate(); } | |
| 120 | public boolean match(Object o) { return o != null && ((AuctionEntry) o).checkUpdate(); } | |
| 175 | 121 | }); |
| 176 | 122 | if (result != null) { |
| 177 | 123 | boolean forcedUpdate = result.isUpdateForced(); |
| 178 | 124 | |
| 179 | if(doUpdate(result) || forcedUpdate) { | |
| 125 | doUpdate(result); | |
| 126 | if(forcedUpdate) { | |
| 180 | 127 | MQFactory.getConcrete("redraw").enqueue(getName()); |
| 181 | 128 | } |
| 182 | 129 | } |
| 526 | 1000 | |
|---|---|---|
| 3 | 3 | import com.jbidwatcher.util.html.JHTML; |
| 4 | 4 | import com.jbidwatcher.util.http.CookieJar; |
| 5 | 5 | import com.jbidwatcher.util.Currency; |
| 6 | import com.jbidwatcher.auction.AuctionEntry; | |
| 7 | 6 | |
| 8 | 7 | /** |
| 9 | 8 | * Created by IntelliJ IDEA. |
| --- | --- | |
| 14 | 13 | * Abstraction of the bidding interface, so it can be replaced with other bidding code, if desired. |
| 15 | 14 | */ |
| 16 | 15 | public interface Bidder { |
| 17 | JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr, int inQuant) throws com.jbidwatcher.auction.BadBidException; | |
| 16 | JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr) throws com.jbidwatcher.auction.BadBidException; | |
| 18 | 17 | |
| 19 | 18 | int buy(AuctionEntry ae, int quantity); |
| 20 | 19 | |
| 729 | 1000 | |
|---|---|---|
| 5 | 5 | * User: Morgan |
| 6 | 6 | * Date: Jan 14, 2009 |
| 7 | 7 | * Time: 4:10:53 AM |
| 8 | * To change this template use File | Settings | File Templates. | |
| 8 | * All 'entry' objects have 'getIdentifier' as a method. | |
| 9 | 9 | */ |
| 10 | 10 | public interface EntryInterface extends Snipeable { |
| 11 | 11 | /** |
| 688 | 1000 | |
|---|---|---|
| 1 | 1 | package com.jbidwatcher.auction; |
| 2 | 2 | |
| 3 | import com.jbidwatcher.auction.server.AuctionServer; | |
| 4 | ||
| 5 | 3 | /** |
| 6 | 4 | * Created by IntelliJ IDEA. |
| 7 | 5 | * User: Morgan |
| 8 | 6 | * Date: Jun 29, 2008 |
| 9 | 7 | * Time: 11:59:12 PM |
| 10 | * To change this template use File | Settings | File Templates. | |
| 8 | * | |
| 9 | * The resolver really exists to abstract the AuctionServerManager's key function: getting the default server. | |
| 11 | 10 | */ |
| 12 | 11 | public interface Resolver { |
| 13 | 12 | AuctionServerInterface getServer(); |
| 800 | 1000 | |
|---|---|---|
| 98 | 98 | // Get Bid Key/Form |
| 99 | 99 | try { |
| 100 | 100 | JConfig.increment("stats.presniped"); |
| 101 | mBidForm = mBidder.getBidForm(mCJ, mEntry, mEntry.getSnipeAmount(), mEntry.getSnipeQuantity()); | |
| 101 | mBidForm = mBidder.getBidForm(mCJ, mEntry, mEntry.getSnipeAmount()); | |
| 102 | 102 | } catch (BadBidException bbe) { |
| 103 | 103 | String result = getSnipeResult(bbe.getResult(), mEntry.getTitle(), mEntry); |
| 104 | 104 | mEntry.setLastStatus(result); |
| --- | --- | |
| 116 | 116 | if(snipeResult == AuctionServerInterface.BID_WINNING || snipeResult == AuctionServerInterface.BID_SELFWIN) { |
| 117 | 117 | snipeOutput = "Successfully sniped a high bid on " + aucTitle + '!'; |
| 118 | 118 | JConfig.increment("stats.sniped.success"); |
| 119 | } else if(snipeResult == AuctionServerInterface.BID_DUTCH_CONFIRMED) { | |
| 120 | snipeOutput = "Successfully sniped a high dutch bid on " + aucTitle + '!'; | |
| 121 | JConfig.increment("stats.sniped.success"); | |
| 122 | 119 | } else { |
| 123 | 120 | switch(snipeResult) { |
| 124 | 121 | case AuctionServerInterface.BID_ERROR_UNKNOWN: |
| 681 | 1000 | |
|---|---|---|
| 21 | 21 | NOT_ADULT, |
| 22 | 22 | BAD_TITLE, |
| 23 | 23 | SELLER_AWAY, |
| 24 | ERROR, | |
| 25 | 24 | CAPTCHA, |
| 26 | 25 | DELETED, |
| 27 | 26 | WRONG_SITE |
| 995 | 1000 | |
|---|---|---|
| 9 | 9 | import com.jbidwatcher.util.xml.XMLElement; |
| 10 | 10 | import com.jbidwatcher.util.xml.XMLParseException; |
| 11 | 11 | import com.jbidwatcher.util.xml.XMLSerialize; |
| 12 | import com.jbidwatcher.util.xml.XMLInterface; | |
| 12 | 13 | |
| 13 | 14 | import java.util.ArrayList; |
| 14 | 15 | import java.util.Date; |
| --- | --- | |
| 51 | 52 | * |
| 52 | 53 | * @param curElement - The current element to load the events from. |
| 53 | 54 | */ |
| 54 | public void fromXML(XMLElement curElement) { | |
| 55 | Iterator<XMLElement> logStep = curElement.getChildren(); | |
| 55 | public void fromXML(XMLInterface curElement) { | |
| 56 | Iterator<XMLInterface> logStep = curElement.getChildren(); | |
| 56 | 57 | |
| 57 | 58 | while(logStep.hasNext()) { |
| 58 | XMLElement curEntry = logStep.next(); | |
| 59 | XMLElement curEntry = (XMLElement)logStep.next(); | |
| 59 | 60 | |
| 60 | 61 | if(curEntry.getTagName().equals("entry")) { |
| 61 | 62 | long msgtime = System.currentTimeMillis(); |
| 62 | 63 | String msg = "Nothing has happened."; |
| 63 | 64 | int curCount = Integer.parseInt(curEntry.getProperty("COUNT")); |
| 64 | 65 | |
| 65 | Iterator<XMLElement> entryStep = curEntry.getChildren(); | |
| 66 | Iterator<XMLInterface> entryStep = curEntry.getChildren(); | |
| 66 | 67 | while(entryStep.hasNext()) { |
| 67 | XMLElement entryField = entryStep.next(); | |
| 68 | XMLElement entryField = (XMLElement)entryStep.next(); | |
| 68 | 69 | if(entryField.getTagName().equals("message")) msg = entryField.getContents(); |
| 69 | 70 | if(entryField.getTagName().equals("date")) msgtime = Long.parseLong(entryField.getContents()); |
| 70 | 71 | } |
| 962 | 1000 | |
|---|---|---|
| 7 | 7 | |
| 8 | 8 | /* |
| 9 | 9 | * @file AuctionServer.java |
| 10 | * @author Morgan Schweers <cyberfox@users.sourceforge.net> | |
| 10 | * @author Morgan Schweers <cyberfox@jbidwatcher.com> | |
| 11 | 11 | * @date Wed Oct 9 13:49:02 2002 |
| 12 | 12 | * @note Library GPL'ed. |
| 13 | 13 | * @brief This is an interface description for the general auction Servers |
| --- | --- | |
| 56 | 56 | public abstract void addSearches(SearchManagerInterface searchManager); |
| 57 | 57 | |
| 58 | 58 | // Exposed to AuctionEntry for checking high bidder status. |
| 59 | public abstract boolean isHighDutch(EntryInterface inAE); | |
| 60 | 59 | public abstract void updateHighBid(AuctionEntry ae); |
| 61 | 60 | |
| 62 | 61 | public abstract void setSnipe(AuctionEntry snipeOn); |
| --- | --- | |
| 358 | 357 | } |
| 359 | 358 | } |
| 360 | 359 | |
| 361 | public int getCount() { | |
| 362 | return AuctionEntry.count(); | |
| 363 | } | |
| 364 | ||
| 365 | 360 | protected abstract String getUserId(); |
| 366 | 361 | |
| 367 | 362 | /** |
| 893 | 1000 | |
|---|---|---|
| 11 | 11 | import com.jbidwatcher.util.xml.XMLElement; |
| 12 | 12 | import com.jbidwatcher.util.xml.XMLParseException; |
| 13 | 13 | import com.jbidwatcher.util.xml.XMLSerialize; |
| 14 | import com.jbidwatcher.util.xml.XMLInterface; | |
| 14 | 15 | import com.jbidwatcher.util.config.JConfig; |
| 15 | 16 | import com.jbidwatcher.util.StringTools; |
| 16 | 17 | import com.jbidwatcher.auction.*; |
| --- | --- | |
| 48 | 49 | * @param inXML - The XML source to load from. |
| 49 | 50 | * @noinspection ThrowInsideCatchBlockWhichIgnoresCaughtException,StringContatenationInLoop |
| 50 | 51 | */ |
| 51 | public void fromXML(XMLElement inXML) { | |
| 52 | Iterator<XMLElement> serversStep = inXML.getChildren(); | |
| 52 | public void fromXML(XMLInterface inXML) { | |
| 53 | Iterator<XMLInterface> serversStep = inXML.getChildren(); | |
| 53 | 54 | |
| 54 | 55 | while(serversStep.hasNext()) { |
| 55 | XMLElement perServer = serversStep.next(); | |
| 56 | XMLInterface perServer = serversStep.next(); | |
| 56 | 57 | // Only process the 'server' entries. |
| 57 | 58 | if(perServer.getTagName().equals("server")) { |
| 58 | 59 | AuctionServer newServer = null; |
| --- | --- | |
| 251 | 252 | } |
| 252 | 253 | } |
| 253 | 254 | |
| 254 | private void getServerAuctionEntries(AuctionServer newServer, XMLElement perServer) { | |
| 255 | private void getServerAuctionEntries(AuctionServer newServer, XMLInterface perServer) { | |
| 255 | 256 | try { |
| 256 | Iterator<XMLElement> entryStep = perServer.getChildren(); | |
| 257 | Iterator<XMLInterface> entryStep = perServer.getChildren(); | |
| 257 | 258 | int count = 0; |
| 258 | 259 | while (entryStep.hasNext()) { |
| 259 | XMLElement perEntry = entryStep.next(); | |
| 260 | XMLInterface perEntry = entryStep.next(); | |
| 260 | 261 | AuctionEntry ae = new AuctionEntry(); |
| 261 | 262 | |
| 262 | 263 | ae.setServer(newServer); |
| 990 | 1000 | |
|---|---|---|
| 798 | 798 | |
| 799 | 799 | private void checkHighBidder() { |
| 800 | 800 | String bidder = null; |
| 801 | String email = null; | |
| 802 | 801 | |
| 803 | 802 | if(mDocument.grep("This is a private listing.*") != null) { |
| 804 | 803 | bidder = "(private)"; |
| --- | --- | |
| 809 | 808 | if (bidder != null) { |
| 810 | 809 | setNumBids(1); |
| 811 | 810 | bidder = bidder.trim(); |
| 812 | email = findHighBidderEmail(bidder); | |
| 813 | 811 | } |
| 814 | 812 | } else { |
| 815 | 813 | if (getQuantity() > 1) { |
| --- | --- | |
| 819 | 817 | bidder = mDocument.getNextContentAfterRegex(T.s("ebayServer.highBidder")); |
| 820 | 818 | if (bidder != null) { |
| 821 | 819 | bidder = bidder.trim(); |
| 822 | email = findHighBidderEmail(bidder); | |
| 823 | 820 | } else { |
| 824 | 821 | bidder = "(unknown)"; // ...but present. |
| 825 | 822 | } |
| --- | --- | |
| 829 | 826 | } |
| 830 | 827 | |
| 831 | 828 | setHighBidder(bidder == null ? "" : bidder); |
| 832 | setHighBidderEmail(email == null ? "(unknown)" : email); | |
| 833 | 829 | } |
| 834 | 830 | |
| 835 | private String findHighBidderEmail(String bidder) { | |
| 836 | String email = null; | |
| 837 | ||
| 838 | if(bidder != null) { | |
| 839 | email = mDocument.getNextContentAfterContent(bidder, true, false); | |
| 840 | if (email != null) { | |
| 841 | email = email.trim(); | |
| 842 | if (email.charAt(0) == '(' && email.charAt(email.length() - 1) == ')' && email.indexOf('@') != -1) { | |
| 843 | email = (email.substring(1, email.length() - 1)); | |
| 844 | } | |
| 845 | if (email.equals("(")) email = null; | |
| 846 | } | |
| 847 | } | |
| 848 | ||
| 849 | return email; | |
| 850 | } | |
| 851 | ||
| 852 | 831 | private int getBidCount(JHTML doc, int quantity) { |
| 853 | 832 | String rawBidCount = doc.getNextContentAfterRegex(T.s("ebayServer.bidCount")); |
| 854 | 833 | if (rawBidCount == null) { |
| 968 | 1000 | |
|---|---|---|
| 11 | 11 | import com.jbidwatcher.util.*; |
| 12 | 12 | import com.jbidwatcher.util.config.JConfig; |
| 13 | 13 | import com.jbidwatcher.util.queue.MQFactory; |
| 14 | import com.jbidwatcher.my.MyJBidwatcher; | |
| 14 | //import com.jbidwatcher.my.MyJBidwatcher; | |
| 15 | 15 | |
| 16 | 16 | import java.net.URLConnection; |
| 17 | 17 | import java.io.IOException; |
| --- | --- | |
| 53 | 53 | mResultHash.put("your bid must be at least ", AuctionServer.BID_ERROR_TOO_LOW); /*?*/ |
| 54 | 54 | mResultHash.put("you('ve| have) been outbid by another bidder", AuctionServer.BID_ERROR_OUTBID); |
| 55 | 55 | mResultHash.put("you('ve| have) just been outbid", ebayServer.BID_ERROR_OUTBID); |
| 56 | mResultHash.put("your bid is confirmed!", AuctionServer.BID_DUTCH_CONFIRMED); | |
| 57 | mResultHash.put("you('re| are) bidding on this multiple item auction", AuctionServer.BID_DUTCH_CONFIRMED); | |
| 58 | mResultHash.put("you('re| are) the high bidder on all items you bid on", AuctionServer.BID_DUTCH_CONFIRMED); | |
| 59 | 56 | mResultHash.put("you('re| are) the current high bidder", AuctionServer.BID_WINNING); |
| 60 | 57 | mResultHash.put("you('re| are) the first bidder", AuctionServer.BID_WINNING); |
| 61 | 58 | mResultHash.put("you('re| are) the high bidder and currently in the lead", AuctionServer.BID_WINNING); |
| --- | --- | |
| 98 | 95 | * @param cj - The cookies for the current session. |
| 99 | 96 | * @param inEntry - The auction being bid on. |
| 100 | 97 | * @param inCurr - The amount to bid. |
| 101 | * @param inQuant - The quantity to bid on (if it's a dutch auction, 1 otherwise). | |
| 102 | * | |
| 103 | 98 | * @return - A Form object containing all the input fields from the bid-confirmation page's form. |
| 104 | 99 | * |
| 105 | 100 | * @throws BadBidException - If there's some kind of an error on the bid confirmation page. |
| 106 | 101 | */ |
| 107 | public JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr, int inQuant) throws BadBidException { | |
| 102 | public JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr) throws BadBidException { | |
| 108 | 103 | String bidRequest = Externalized.getString("ebayServer.protocol") + T.s("ebayServer.bidHost") + Externalized.getString("ebayServer.V3file"); |
| 109 | String bidInfo = getBidInfoURL(inEntry, inCurr, inQuant); | |
| 104 | String bidInfo = getBidInfoURL(inEntry, inCurr); | |
| 110 | 105 | BidFormReturn rval = null; |
| 111 | 106 | |
| 112 | 107 | try { |
| --- | --- | |
| 135 | 130 | checkSignOn(rval.getDocument()); |
| 136 | 131 | checkBidErrors(rval); |
| 137 | 132 | } |
| 133 | // TODO -- Move this to a registered 'alternative parsing' class, which iterates over objects calling recognizeBidPage until getting a positive result, or running out. | |
| 134 | // if(JConfig.queryConfiguration("my.jbidwatcher.enabled", "false").equals("true") && | |
| 135 | // JConfig.queryConfiguration("my.jbidwatcher.id") != null) { | |
| 136 | // String recognize = MyJBidwatcher.getInstance().recognizeBidpage(inEntry.getIdentifier(), rval.getBuffer()); | |
| 137 | // Integer remote_result = null; | |
| 138 | // try { | |
| 139 | // remote_result = Integer.parseInt(recognize); | |
| 140 | // } catch(NumberFormatException nfe) { | |
| 141 | // // Ignore it for now... | |
| 142 | // JConfig.log().logDebug(recognize); | |
| 143 | // } | |
| 144 | // | |
| 145 | // if(remote_result != null && remote_result != AuctionServer.BID_ERROR_UNKNOWN) { | |
| 146 | // throw new BadBidException("Remote-checked result", remote_result); | |
| 147 | // } | |
| 148 | // } | |
| 138 | 149 | |
| 139 | if(JConfig.queryConfiguration("my.jbidwatcher.enabled", "false").equals("true") && | |
| 140 | JConfig.queryConfiguration("my.jbidwatcher.id") != null) { | |
| 141 | String recognize = MyJBidwatcher.getInstance().recognizeBidpage(inEntry.getIdentifier(), rval.getBuffer()); | |
| 142 | Integer remote_result = null; | |
| 143 | try { | |
| 144 | remote_result = Integer.parseInt(recognize); | |
| 145 | } catch(NumberFormatException nfe) { | |
| 146 | // Ignore it for now... | |
| 147 | JConfig.log().logDebug(recognize); | |
| 148 | } | |
| 149 | ||
| 150 | if(remote_result != null && remote_result != AuctionServer.BID_ERROR_UNKNOWN) { | |
| 151 | throw new BadBidException("Remote-checked result", remote_result); | |
| 152 | } | |
| 153 | } | |
| 154 | ||
| 155 | 150 | if(JConfig.debugging) inEntry.setLastStatus("Failed to bid. 'Show Last Error' from context menu to see the failure page from the bid attempt."); |
| 156 | 151 | JConfig.log().dump2File("unknown-" + inEntry.getIdentifier() + ".html", rval.getBuffer()); |
| 157 | 152 | inEntry.setErrorPage(rval.getBuffer()); |
| --- | --- | |
| 174 | 169 | return pageName; |
| 175 | 170 | } |
| 176 | 171 | |
| 177 | private String getBidInfoURL(AuctionEntry inEntry, Currency inCurr, int inQuant) { | |
| 172 | private String getBidInfoURL(AuctionEntry inEntry, Currency inCurr) { | |
| 178 | 173 | String bidInfo = Externalized.getString("ebayServer.bidCmd") + "&co_partnerid=" + Externalized.getString("ebayServer.itemCGI") + inEntry.getIdentifier() + "&fb=2"; |
| 179 | if(inEntry.isDutch()) { | |
| 180 | bidInfo += Externalized.getString("ebayServer.quantCGI") + inQuant; | |
| 181 | } | |
| 182 | 174 | bidInfo += Externalized.getString("ebayServer.bidCGI") + inCurr.getValue(); |
| 183 | 175 | return bidInfo; |
| 184 | 176 | } |
| --- | --- | |
| 311 | 303 | JHTML.Form bidForm; |
| 312 | 304 | |
| 313 | 305 | try { |
| 314 | bidForm = getBidForm(cj, inEntry, inBid, inQuantity); | |
| 306 | bidForm = getBidForm(cj, inEntry, inBid); | |
| 315 | 307 | } catch(BadBidException bbe) { |
| 316 | 308 | UpdateBlocker.endBlocking(); |
| 317 | 309 | return bbe.getResult(); |
| 969 | 1000 | |
|---|---|---|
| 303 | 303 | } |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | private boolean checkSecurityConfirmation(JHTML doc) throws IOException, CaptchaException { | |
| 306 | private boolean checkSecurityConfirmation(JHTML doc) throws CaptchaException { | |
| 307 | 307 | if(doc.grep(T.s("security.measure")) != null || |
| 308 | 308 | doc.grep(T.s("enter.verification.code")) != null || |
| 309 | 309 | doc.grep(T.s("enter.a.verification.code.to.continue")) != null || |
| 997 | 1000 | |
|---|---|---|
| 93 | 93 | * |
| 94 | 94 | */ |
| 95 | 95 | public ServerMenu establishMenu() { |
| 96 | ebayServerMenu esm = new ebayServerMenu(this, Constants.EBAY_DISPLAY_NAME, 'b'); | |
| 96 | ServerMenu esm = new ebayServerMenu(this, Constants.EBAY_DISPLAY_NAME, 'b'); | |
| 97 | 97 | esm.initialize(); |
| 98 | 98 | |
| 99 | 99 | return esm; |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | /** | |
| 103 | * @brief Very simplistic check to see if the current user is the | |
| 104 | * high bidder on a Dutch item. | |
| 105 | * | |
| 106 | * This only works, really, on closed items, I believe. It shows | |
| 107 | * you as a 'winner' always, otherwise. | |
| 108 | * | |
| 109 | * @param inAE - The auction entry to check. | |
| 110 | * | |
| 111 | * @return - true if the user is one of the high bidders on a dutch item, false otherwise. | |
| 112 | */ | |
| 113 | public boolean isHighDutch(EntryInterface inAE) { | |
| 114 | String dutchWinners = Externalized.getString("ebayServer.protocol") + T.s("ebayServer.dutchRequestHost") + Externalized.getString("ebayServer.V3WS3File") + Externalized.getString("ebayServer.viewDutch") + inAE.getIdentifier(); | |
| 115 | CookieJar cj = mLogin.getNecessaryCookie(false); | |
| 116 | String userCookie = null; | |
| 117 | if (cj != null) userCookie = cj.toString(); | |
| 118 | ||
| 119 | JHTML htmlDocument = new JHTML(dutchWinners, userCookie, mCleaner); | |
| 120 | String matchedName = null; | |
| 121 | if(htmlDocument.isLoaded()) { | |
| 122 | matchedName = htmlDocument.getNextContentAfterContent(mLogin.getUserId()); | |
| 123 | } | |
| 124 | ||
| 125 | return matchedName != null; | |
| 126 | } | |
| 127 | ||
| 128 | 102 | public void updateHighBid(AuctionEntry ae) { |
| 129 | 103 | String bidHistory = Externalized.getString("ebayServer.protocol") + T.s("ebayServer.bidHost") + Externalized.getString("ebayServer.V3file") + Externalized.getString("ebayServer.viewBidsCGI") + ae.getIdentifier(); |
| 130 | 104 | CookieJar cj = mLogin.getNecessaryCookie(false); |
| --- | --- | |
| 359 | 333 | } |
| 360 | 334 | |
| 361 | 335 | // These two are called by sniping. |
| 362 | public JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr, int inQuant) throws BadBidException { | |
| 336 | public JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr) throws BadBidException { | |
| 363 | 337 | return new JHTML.Form("<form action=\"http://example.com\">"); |
| 364 | 338 | } |
| 365 | 339 | |
| --- | --- | |
| 461 | 435 | return new ebayAuction(T); |
| 462 | 436 | } |
| 463 | 437 | |
| 464 | /** | |
| 465 | * @brief Returns the amount of time it takes to retrieve a page | |
| 466 | * from the auction server. | |
| 467 | * | |
| 468 | * @return The amount of milliseconds it takes to get a simple page | |
| 469 | * from the auction server. | |
| 470 | */ | |
| 471 | private long getSnipePadding() { | |
| 472 | return 1; | |
| 473 | } | |
| 474 | ||
| 475 | 438 | public StringBuffer getAuction(String id) throws FileNotFoundException { |
| 476 | 439 | long pre = System.currentTimeMillis(); |
| 477 | 440 | StringBuffer sb = getAuction(getURLFromItem(id)); |
| --- | --- | |
| 534 | 497 | if(s == null) searchManager.addSearch("My Items", "My eBay", "", Constants.EBAY_SERVER_NAME, -1, 1); |
| 535 | 498 | } |
| 536 | 499 | |
| 537 | /** | |
| 538 | * @brief Get the list of bidders on an item. | |
| 539 | * | |
| 540 | * This is primarily useful for networks-of-interest searching. | |
| 541 | * | |
| 542 | * @param ae - The item you are interested in. | |
| 543 | * | |
| 544 | * @return - A list containing strings with the names of each | |
| 545 | * user who was interested in the item enough to bid. | |
| 546 | */ | |
| 547 | public List<String> getBidderNames(EntryInterface ae) { | |
| 548 | CookieJar cj = mLogin.getNecessaryCookie(false); | |
| 549 | String userCookie = null; | |
| 550 | if (cj != null) userCookie = cj.toString(); | |
| 551 | JHTML htmlDocument = new JHTML(Externalized.getString("ebayServer.protocol") + T.s("ebayServer.bidderNamesHost") + Externalized.getString("ebayServer.file") + Externalized.getString("ebayServer.viewBidsCGI") + ae.getIdentifier(), userCookie, mCleaner); | |
| 552 | ||
| 553 | String curName = htmlDocument.getNextContentAfterContent(T.s("ebayServer.bidListPrequel")); | |
| 554 | ||
| 555 | if(curName == null) { | |
| 556 | JConfig.log().logMessage("Problem with loaded page when getting bidder names for auction " + ae.getIdentifier()); | |
| 557 | return null; | |
| 558 | } | |
| 559 | ||
| 560 | List<String> outNames = new ArrayList<String>(); | |
| 561 | ||
| 562 | do { | |
| 563 | if(!outNames.contains(curName)) { | |
| 564 | outNames.add(curName); | |
| 565 | } | |
| 566 | curName = htmlDocument.getNextContent(); | |
| 567 | while(curName != null && ! (curName.endsWith("PDT") || curName.endsWith("PST"))) { | |
| 568 | curName = htmlDocument.getNextContent(); | |
| 569 | } | |
| 570 | if(curName != null) curName = htmlDocument.getNextContent(); | |
| 571 | if(curName != null) { | |
| 572 | if(curName.indexOf(T.s("ebayServer.earlierCheck")) != -1) curName = null; | |
| 573 | } | |
| 574 | } while(curName != null); | |
| 575 | ||
| 576 | return outNames; | |
| 577 | } | |
| 578 | ||
| 579 | 500 | private void doMyEbaySynchronize(String label) { |
| 580 | 501 | MQFactory.getConcrete("Swing").enqueue("Synchronizing with My eBay..."); |
| 581 | 502 | mSearcher.getMyEbayItems(mLogin.getUserId(), label); |
| --- | --- | |
| 689 | 610 | } |
| 690 | 611 | |
| 691 | 612 | public long getAdjustedTime() { |
| 692 | return System.currentTimeMillis() + getServerTimeDelta() + getPageRequestTime() + getSnipePadding(); | |
| 613 | return System.currentTimeMillis() + getServerTimeDelta() + getPageRequestTime(); | |
| 693 | 614 | } |
| 694 | 615 | |
| 695 | 616 | public long getServerTimeDelta() { |
| 981 | 1000 | |
|---|---|---|
| 12 | 12 | import com.jbidwatcher.util.queue.SuperQueue; |
| 13 | 13 | import com.jbidwatcher.util.xml.XMLSerialize; |
| 14 | 14 | import com.jbidwatcher.util.xml.XMLElement; |
| 15 | import com.jbidwatcher.util.xml.XMLInterface; | |
| 15 | 16 | import com.jbidwatcher.util.http.Http; |
| 16 | 17 | import com.jbidwatcher.util.http.ClientHttpRequest; |
| 17 | 18 | import com.jbidwatcher.auction.AuctionEntry; |
| --- | --- | |
| 250 | 251 | if(sb == null) return false; |
| 251 | 252 | XMLElement xml = new XMLElement(); |
| 252 | 253 | xml.parseString(sb.toString()); |
| 253 | XMLElement sync = xml.getChild("syncq"); | |
| 254 | XMLElement expires = xml.getChild("expiry"); | |
| 255 | XMLElement listingsRemaining = xml.getChild("listings"); | |
| 256 | XMLElement categoriesRemaining = xml.getChild("categories"); | |
| 257 | XMLElement reporting = xml.getChild("reportq"); | |
| 258 | XMLElement snipesListen = xml.getChild("snipes"); | |
| 259 | XMLElement ssl = xml.getChild("ssl"); | |
| 260 | XMLElement uploadHTML = xml.getChild("uploadhtml"); | |
| 261 | XMLElement serverParser = xml.getChild("parser"); | |
| 262 | XMLElement gixen = xml.getChild("gixen"); | |
| 254 | XMLInterface sync = xml.getChild("syncq"); | |
| 255 | XMLInterface expires = xml.getChild("expiry"); | |
| 256 | XMLInterface listingsRemaining = xml.getChild("listings"); | |
| 257 | XMLInterface categoriesRemaining = xml.getChild("categories"); | |
| 258 | XMLInterface reporting = xml.getChild("reportq"); | |
| 259 | XMLInterface snipesListen = xml.getChild("snipes"); | |
| 260 | XMLInterface ssl = xml.getChild("ssl"); | |
| 261 | XMLInterface uploadHTML = xml.getChild("uploadhtml"); | |
| 262 | XMLInterface serverParser = xml.getChild("parser"); | |
| 263 | XMLInterface gixen = xml.getChild("gixen"); | |
| 263 | 264 | |
| 264 | 265 | if(expires != null) { |
| 265 | 266 | String date = expires.getContents(); |
| --- | --- | |
| 291 | 292 | return mSyncQueueURL != null && mReportQueueURL != null; |
| 292 | 293 | } |
| 293 | 294 | |
| 294 | private boolean getBoolean(XMLElement x) { | |
| 295 | private boolean getBoolean(XMLInterface x) { | |
| 295 | 296 | boolean rval = false; |
| 296 | 297 | if(x != null) { |
| 297 | 298 | String contents = x.getContents(); |
| 530 | 1000 | |
|---|---|---|
| 2 | 2 | |
| 3 | 3 | import com.jbidwatcher.auction.Auctions; |
| 4 | 4 | |
| 5 | import javax.swing.*; | |
| 6 | 5 | import java.awt.Color; |
| 7 | 6 | import java.awt.event.ActionListener; |
| 8 | 7 | |
| --- | --- | |
| 26 | 25 | return mDeletable; |
| 27 | 26 | } |
| 28 | 27 | |
| 29 | public void setDeletable(boolean deletable) { | |
| 30 | mDeletable = deletable; | |
| 31 | } | |
| 32 | ||
| 33 | 28 | AuctionListHolder(String name) { |
| 34 | this(name, false, false, true); | |
| 29 | this(name, false, true); | |
| 35 | 30 | } |
| 36 | 31 | |
| 37 | 32 | AuctionListHolder(String name, Color presetBackground) { |
| 38 | this(name, false, false, true); | |
| 33 | this(name, false, true); | |
| 39 | 34 | mAuctionUI.setBackground(presetBackground); |
| 40 | 35 | } |
| 41 | 36 | |
| 42 | AuctionListHolder(String name, boolean _completed, boolean _selling, boolean deletable) { | |
| 37 | AuctionListHolder(String name, boolean _completed, boolean deletable) { | |
| 43 | 38 | mAuctionList = new Auctions(name); |
| 44 | 39 | if(_completed) mAuctionList.setComplete(); |
| 45 | if(_selling) mAuctionList.setSelling(); | |
| 46 | 40 | mAuctionUI = new AuctionsUIModel(mAuctionList, sTableContext, sFrameContext, sCornerButtonListener); |
| 47 | 41 | mDeletable = deletable; |
| 48 | 42 | JTabManager.getInstance().add(name, mAuctionUI.getPanel(), mAuctionUI.getTableSorter()); |
| 974 | 1000 | |
|---|---|---|
| 156 | 156 | return FilterManager.getInstance().getAuctionIterator(); |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | public void loadAuctionsFromDB() { | |
| 160 | int auctionTotal = AuctionServerManager.getInstance().getServer().getCount(); | |
| 161 | MQFactory.getConcrete("splash").enqueue("SET 0"); | |
| 162 | MQFactory.getConcrete("splash").enqueue("WIDTH " + auctionTotal); | |
| 163 | ||
| 164 | MQFactory.getConcrete("splash").enqueue("SET 100"); | |
| 165 | } | |
| 166 | ||
| 167 | 159 | /** |
| 168 | 160 | * @brief Load auctions from a save file, with a pretty splash |
| 169 | 161 | * screen and everything, if necessary. |
| --- | --- | |
| 304 | 296 | if(newSaveFile.exists()) newSaveFile.delete(); |
| 305 | 297 | } |
| 306 | 298 | |
| 307 | StringBuffer buf = buildSaveBuffer(auctionsData, null); | |
| 299 | StringBuffer buf = buildSaveBuffer(auctionsData); | |
| 308 | 300 | boolean saveDone = true; |
| 309 | 301 | |
| 310 | 302 | // Dump the save file out! |
| --- | --- | |
| 344 | 336 | if(!saveParent.exists()) saveParent.mkdirs(); // This can fail, but we don't mind. |
| 345 | 337 | } |
| 346 | 338 | |
| 347 | public static StringBuffer buildSaveBuffer(XMLElement auctionsData, XMLElement deletedData) { | |
| 339 | public static StringBuffer buildSaveBuffer(XMLElement auctionsData) { | |
| 348 | 340 | synchronized(_saveBuf) { |
| 349 | 341 | _saveBuf.setLength(0); |
| 350 | 342 | _saveBuf.append("<?xml version=\"1.0\"?>\n\n"); |
| --- | --- | |
| 352 | 344 | _saveBuf.append('\n'); |
| 353 | 345 | _saveBuf.append("<jbidwatcher format=\"0101\">\n"); |
| 354 | 346 | auctionsData.toStringBuffer(_saveBuf, 1); |
| 355 | if(deletedData != null) { | |
| 356 | deletedData.toStringBuffer(_saveBuf, 1); | |
| 357 | } | |
| 358 | 347 | _saveBuf.append("</jbidwatcher>"); |
| 359 | 348 | } |
| 360 | 349 | return _saveBuf; |
