avatar

497

Lots of refactorings to make the bidding process more consistent, and more comprehensible code. It also should have fewer side effects, which should help sniping a bit.

by mrs, 18 Jun, 2008 03:24 AM
496 497  
77 import com.jbidwatcher.util.http.Http;
88 import com.jbidwatcher.util.Externalized;
99 import com.jbidwatcher.util.config.ErrorManagement;
10 import com.jbidwatcher.util.script.Scripting;
1110 import com.jbidwatcher.util.StringTools;
1211 import com.jbidwatcher.util.Currency;
1312 import com.jbidwatcher.util.UpdateBlocker;
1413 import com.jbidwatcher.util.config.JConfig;
1514 import com.jbidwatcher.util.queue.MQFactory;
16 import com.jbidwatcher.app.MyJBidwatcher;
15 import com.jbidwatcher.my.MyJBidwatcher;
1716 
1817 import java.net.URLConnection;
1918 import java.io.IOException;
------
9190     mResultHash.put("sign in", AuctionServer.BID_ERROR_CANT_SIGN_IN);
9291   }
9392 
93   /**
94    * Get the bidding form (with bid key) from the basic bid page.
95    *
96    * @param cj - The cookies for the current session.
97    * @param inEntry - The auction being bid on.
98    * @param inCurr - The amount to bid.
99    * @param inQuant - The quantity to bid on (if it's a dutch auction, 1 otherwise).
100    *
101    * @return - A Form object containing all the input fields from the bid-confirmation page's form.
102    *
103    * @throws BadBidException - If there's some kind of an error on the bid confirmation page.
104    */
94105   public JHTML.Form getBidForm(CookieJar cj, AuctionEntry inEntry, Currency inCurr, int inQuant) throws BadBidException {
95106     String bidRequest = Externalized.getString("ebayServer.protocol") + Externalized.getString("ebayServer.bidHost") + Externalized.getString("ebayServer.V3file");
96     String bidInfo;
97     if(inEntry.isDutch()) {
98       bidInfo = Externalized.getString("ebayServer.bidCmd") + "&co_partnerid=" + Externalized.getString("ebayServer.itemCGI") + inEntry.getIdentifier() +
99                 "&fb=2" + Externalized.getString("ebayServer.quantCGI") + inQuant +
100                 Externalized.getString("ebayServer.bidCGI") + inCurr.getValue();
101     } else {
102       bidInfo = Externalized.getString("ebayServer.bidCmd") + "&co_partnerid=" + Externalized.getString("ebayServer.itemCGI") + inEntry.getIdentifier() + "&fb=2" +
103                 Externalized.getString("ebayServer.bidCGI") + inCurr.getValue();
104     }
105     StringBuffer loadedPage = null;
106     JHTML htmlDocument = null;
107     String bidInfo = getBidInfoURL(inEntry, inCurr, inQuant);
108     BidFormReturn rval = null;
107109 
108110     try {
109111       String pageName = bidRequest + '?' + bidInfo;
110       boolean checked_signon = false;
111       boolean checked_reminder = false;
112       boolean done = false;
113       boolean post = false;
114       while (!done) {
115         done = true;
116112 
117         if(JConfig.debugging) inEntry.setLastStatus("Loading bid request...");
118         URLConnection huc = cj.getAllCookiesFromPage(pageName, null, post);
119         post = false;
120         //  We failed to load, entirely.  Punt.
121         if (huc == null) return null;
113       if (JConfig.debugging) inEntry.setLastStatus("Loading bid request...");
114       rval = getBidFormInternal(pageName, inEntry, cj);
122115 
123         loadedPage = Http.receivePage(huc);
124         //  We failed to load.  Punt.
125         if (loadedPage == null) {
126           return null;
127         } else if(JConfig.debugging() && JConfig.queryConfiguration("my.jbidwatcher.id") != null) {
128           String result = MyJBidwatcher.getInstance().recognizeBidpage(inEntry, loadedPage);
129 //          String result = (String) Scripting.rubyMethod("recognize_bidpage", inEntry, loadedPage);
130           ErrorManagement.logDebug(result);
131         }
116       if ( !rval.isSuccess() && (cj = checkSignin(inEntry, rval.getDocument())) != null) {
117         rval = getBidFormInternal(pageName, inEntry, cj);
118       }
132119 
133         htmlDocument = new JHTML(loadedPage);
134         JHTML.Form bidForm = htmlDocument.getFormWithInput("key");
135         if(bidForm != null) {
136           if(JConfig.debugging) inEntry.setLastStatus("Done loading bid request, got form...");
137           return bidForm;
138         }
120       if( !rval.isSuccess() && (pageName = checkForWarning(inEntry, rval.getDocument())) != null) {
121         rval = getBidFormInternal(pageName, inEntry, cj);
122       }
139123 
140         if(!checked_signon) {
141           checked_signon = true;
142           String signOn = htmlDocument.getTitle();
143           if (signOn != null) {
144             ErrorManagement.logDebug("Checking sign in as bid key load failed!");
145             if (StringTools.startsWithIgnoreCase(signOn, "sign in")) {
146               //  This means we somehow failed to keep the login in place.  Bad news, in the middle of a snipe.
147               ErrorManagement.logDebug("Being prompted again for sign in, retrying.");
148               if(JConfig.debugging) inEntry.setLastStatus("Not done loading bid request, got re-login request...");
149               mLogin.resetCookie();
150               mLogin.getNecessaryCookie(true);
151               if(JConfig.debugging) inEntry.setLastStatus("Done re-logging in, retrying load bid request.");
152               done = false;
153             }
154           }
155         }
156 
157         if(!checked_reminder) {
158           if(htmlDocument.grep(Externalized.getString("ebayServer.warningPage")) != null) {
159             checked_reminder = true;
160             JHTML.Form continueForm = htmlDocument.getFormWithInput("firedFilterId");
161             if(continueForm != null) {
162               inEntry.setLastStatus("Trying to 'continue' for the actual bid.");
163               pageName = continueForm.getCGI();
164               pageName = pageName.replaceFirst("%[A-F][A-F0-9]%A0", "%A0");
165               done = false;
166               post = false;
167             }
168           }
169         }
170       }
124       if (rval.isSuccess()) return rval.getForm();
171125     } catch (IOException e) {
172126       ErrorManagement.handleException("Failure to get the bid key!  BID FAILURE!", e);
173127     }
174128 
175     if(htmlDocument != null) {
176       String signOn = htmlDocument.getTitle();
177       if(signOn != null && signOn.equalsIgnoreCase("Sign In")) throw new BadBidException("sign in", AuctionServerInterface.BID_ERROR_CANT_SIGN_IN);
178       String errMsg = htmlDocument.grep(mBidResultRegex);
179       if(errMsg != null) {
180         Matcher bidMatch = mFindBidResult.matcher(errMsg);
181         bidMatch.find();
182         String matched_error = bidMatch.group().toLowerCase();
183         throw new BadBidException(matched_error, getMatchedResult(matched_error));
184       } else {
185         String amount = htmlDocument.getNextContentAfterRegex("Enter");
186         if (amount != null) {
187           String orMore = htmlDocument.getNextContent();
188           if (orMore != null && orMore.indexOf("or more") != -1) {
189             throw new BadBidException("Enter " + amount + orMore, ebayServer.BID_ERROR_TOO_LOW);
190           }
191         }
192       }
129     //  If we never got a valid return value (e.g. an exception was thrown early), punt.
130     if(rval == null) return null;
131 
132     if(rval.getDocument() != null) {
133       checkSignOn(rval.getDocument());
134       checkBidErrors(rval.getDocument());
193135     }
194136 
195     if(JConfig.scriptingEnabled() &&
196             JConfig.queryConfiguration("my.jbidwatcher.enabled", "false").equals("true") &&
197             JConfig.queryConfiguration("my.jbidwatcher.id") != null) {
198       String recognize = (String)Scripting.rubyMethod("recognize_bidpage", inEntry, loadedPage);
137     if(JConfig.queryConfiguration("my.jbidwatcher.enabled", "false").equals("true") &&
138        JConfig.queryConfiguration("my.jbidwatcher.id") != null) {
139       String recognize = MyJBidwatcher.getInstance().recognizeBidpage(inEntry.getIdentifier(), rval.getBuffer());
199140       Integer remote_result = null;
200141       try {
201142         remote_result = Integer.parseInt(recognize);
------
210151     }
211152 
212153     if(JConfig.debugging) inEntry.setLastStatus("Failed to bid. 'Show Last Error' from context menu to see the failure page from the bid attempt.");
213     inEntry.setErrorPage(loadedPage);
154     inEntry.setErrorPage(rval.getBuffer());
214155 
215156     //  We don't recognize this error.  Damn.  Log it and freak.
216     ErrorManagement.logFile(bidInfo, loadedPage);
157     ErrorManagement.logFile(bidInfo, rval.getBuffer());
217158     return null;
218159   }
219160 
161   private String checkForWarning(AuctionEntry inEntry, JHTML htmlDocument) throws UnsupportedEncodingException {
162     String pageName = null;
163     if (htmlDocument.grep(Externalized.getString("ebayServer.warningPage")) != null) {
164       JHTML.Form continueForm = htmlDocument.getFormWithInput("firedFilterId");
165       if (continueForm != null) {
166         inEntry.setLastStatus("Trying to 'continue' for the actual bid.");
167         pageName = continueForm.getCGI();
168         pageName = pageName.replaceFirst("%[A-F][A-F0-9]%A0", "%A0");
169       }
170     }
171     return pageName;
172   }
173 
174   private String getBidInfoURL(AuctionEntry inEntry, Currency inCurr, int inQuant) {
175     String bidInfo = Externalized.getString("ebayServer.bidCmd") + "&co_partnerid=" + Externalized.getString("ebayServer.itemCGI") + inEntry.getIdentifier() + "&fb=2";
176     if(inEntry.isDutch()) {
177       bidInfo += Externalized.getString("ebayServer.quantCGI") + inQuant;
178     }
179     bidInfo += Externalized.getString("ebayServer.bidCGI") + inCurr.getValue();
180     return bidInfo;
181   }
182 
183   private CookieJar checkSignin(AuctionEntry inEntry, JHTML htmlDocument) {
184     String signOn = htmlDocument.getTitle();
185     if (signOn != null) {
186       ErrorManagement.logDebug("Checking sign in as bid key load failed!");
187       if (StringTools.startsWithIgnoreCase(signOn, "sign in")) {
188         //  This means we somehow failed to keep the login in place.  Bad news, in the middle of a snipe.
189         ErrorManagement.logDebug("Being prompted again for sign in, retrying.");
190         if(JConfig.debugging) inEntry.setLastStatus("Not done loading bid request, got re-login request...");
191         CookieJar cj = mLogin.getSignInCookie(null);
192         if(JConfig.debugging) inEntry.setLastStatus("Done re-logging in, retrying load bid request.");
193         return cj;
194       }
195     }
196     return null;
197   }
198 
199   private class BidFormReturn {
200     private boolean mSuccess;
201     private JHTML.Form mForm;
202     private JHTML mDocument;
203     private StringBuffer mBuffer;
204 
205     public boolean isSuccess() { return mSuccess; }
206     public JHTML.Form getForm() { return mForm; }
207     public JHTML getDocument() { return mDocument; }
208     public StringBuffer getBuffer() { return mBuffer; }
209 
210     private BidFormReturn(boolean success, JHTML.Form form, JHTML document, StringBuffer buffer) {
211       mSuccess = success;
212       mForm = form;
213       mDocument = document;
214       mBuffer = buffer;
215     }
216   }
217 
218   private BidFormReturn getBidFormInternal(String pageName, AuctionEntry inEntry, CookieJar cj) throws IOException {
219     URLConnection huc = cj.getAllCookiesFromPage(pageName, null, false);
220     StringBuffer loadedPage;
221 
222     //  If we failed to load, punt.  Treat it as success, but with a null form result.
223     if (huc == null || (loadedPage = Http.receivePage(huc)) == null) {
224       return new BidFormReturn(true, null, null, null);
225     }
226 
227     JHTML htmlDocument = new JHTML(loadedPage);
228     JHTML.Form bidForm = htmlDocument.getFormWithInput("key");
229 
230     if (bidForm != null) {
231       if (JConfig.debugging) inEntry.setLastStatus("Done loading bid request, got form...");
232       return new BidFormReturn(true, bidForm, htmlDocument, loadedPage);
233     }
234     return new BidFormReturn(false, null, htmlDocument, loadedPage);
235   }
236 
237   private void checkBidErrors(JHTML htmlDocument) throws BadBidException {
238     String errMsg = htmlDocument.grep(mBidResultRegex);
239     if(errMsg != null) {
240       Matcher bidMatch = mFindBidResult.matcher(errMsg);
241       bidMatch.find();
242       String matched_error = bidMatch.group().toLowerCase();
243       throw new BadBidException(matched_error, getMatchedResult(matched_error));
244     } else {
245       String amount = htmlDocument.getNextContentAfterRegex("Enter");
246       if (amount != null) {
247         String orMore = htmlDocument.getNextContent();
248         if (orMore != null && orMore.indexOf("or more") != -1) {
249           throw new BadBidException("Enter " + amount + orMore, ebayServer.BID_ERROR_TOO_LOW);
250         }
251       }
252     }
253   }
254 
255   private void checkSignOn(JHTML htmlDocument) throws BadBidException {
256     String signOn = htmlDocument.getTitle();
257     if(signOn != null && signOn.equalsIgnoreCase("Sign In")) throw new BadBidException("sign in", AuctionServerInterface.BID_ERROR_CANT_SIGN_IN);
258   }
259 
220260   private Integer getMatchedResult(String matched_text) {
221261     for (String regex : mResultHash.keySet()) {
222262       String hacked = "(?msi).*" + regex.replace(" ", "\\s+") + ".*";
496 497  
149149 
150150   public synchronized CookieJar getSignInCookie(CookieJar old_cj) {
151151     if (getPassword().equals(mBadPassword) && getUserId().equals(mBadUsername)) {
152       ErrorManagement.logDebug("Not getting the sign in cookie; username/password combo hasn't changed.");
152153       return old_cj;
153154     }
154155 
------
179180     boolean isAdult = JConfig.queryConfiguration(mSiteName + ".adult", "false").equals("true");
180181     CookieJar cj = (oldCookie == null) ? new CookieJar() : oldCookie;
181182     String startURL = Externalized.getString("ebayServer.signInPage");
182     if (isAdult) {
183       startURL = Externalized.getString("ebayServer.adultPageLogin");
184     }
183 
184     if (isAdult) startURL = Externalized.getString("ebayServer.adultPageLogin");
185 
185186     URLConnection uc_signin = cj.getAllCookiesFromPage(startURL, null, false);
186187     try {
187188       StringBuffer signin = Http.receivePage(uc_signin);
------
198199           if (getAdultRedirector(uc_signin, cj)) {
199200             if (mNotifySwing) MQFactory.getConcrete("Swing").enqueue("VALID LOGIN");
200201           } else {
201             //  Disable adult mode and try again.
202             ErrorManagement.logMessage("Disabling 'adult' mode and retrying.");
203             JConfig.setConfiguration(mSiteName + ".adult", "false");
204             cj = getSignInCookie(cj, username, password);
205             //  Re-enable adult mode if logging in via non-adult mode still failed...
206             if(cj == null) {
207               JConfig.setConfiguration(mSiteName + ".adult", "true");
208             }
209             return cj;
202             return retryLoginWithoutAdult(cj, username, password);
210203           }
211204         } else {
212205           StringBuffer confirm = Http.receivePage(uc_signin);
213206           ErrorManagement.dump2File("sign_in-2.html", confirm);
214207           JHTML doc = new JHTML(confirm);
208           //  Check for CAPTCHA and bad passwords...
215209           if (checkSecurityConfirmation(doc)) {
216210             cj = null;
217211             MQFactory.getConcrete("login").enqueue("FAILED Sign in information is not valid.");
------
245239     return cj;
246240   }
247241 
242   private CookieJar retryLoginWithoutAdult(CookieJar cj, String username, String password) {//  Disable adult mode and try again.
243     ErrorManagement.logMessage("Disabling 'adult' mode and retrying.");
244     JConfig.setConfiguration(mSiteName + ".adult", "false");
245     cj = getSignInCookie(cj, username, password);
246     //  Re-enable adult mode if logging in via non-adult mode still failed...
247     if(cj == null) {
248       JConfig.setConfiguration(mSiteName + ".adult", "true");
249     }
250     return cj;
251   }
252 
248253   private void notifySecurityIssue() {
249254     MQFactory.getConcrete("Swing").enqueue("NOTIFY " + "eBay's security monitoring has been triggered, and temporarily requires\n" +
250255         "human intervention to log in.  JBidwatcher will not be able to log in\n" +
371 497  
1010 import com.jbidwatcher.util.config.ErrorManagement;
1111 import com.jbidwatcher.util.ByteBuffer;
1212 import com.jbidwatcher.util.Constants;
13 import com.jbidwatcher.util.Parameters;
1314 
1415 import java.net.*;
1516 import java.io.*;
17 import java.util.Map;
1618 
1719 public class Http {
1820   private static void setConnectionProxyInfo(URLConnection huc) {
------
8688     }
8789   }
8890 
89 
9091   public static URLConnection makeRequest(URL source, String cookie) throws java.io.IOException {
9192     URLConnection uc;
9293 
------
265266     }
266267     return(huc);
267268   }
269 
270   public static String postTo(String url, Parameters params) {
271     StringBuffer postData = null;
272     try {
273       postData = createCGIData(params);
274       URLConnection uc = postFormPage(url, postData.toString(), null, null, false);
275       StringBuffer sb = receivePage(uc);
276       return sb == null ? null : sb.toString();
277     } catch (IOException e) {
278       int length = 0;
279       if (postData != null) length = postData.length();
280       ErrorManagement.logDebug("Couldn't send params (length: " + length + ") to " + url);
281       return null;
282     }
283   }
284 
285   private static StringBuffer createCGIData(Parameters data) throws UnsupportedEncodingException {
286     StringBuffer postData = new StringBuffer();
287     boolean first = true;
288     for (Map.Entry<Object, Object> param : data.entrySet()) {
289       Object key = param.getKey();
290       Object value = param.getValue();
291 
292       if (value != null) {
293         if (!first)
294           postData.append('&');
295         else
296           first = false;
297 
298         postData.append(key.toString());
299         postData.append('=');
300         postData.append(URLEncoder.encode(value.toString(), "UTF-8"));
301       }
302     }
303     return postData;
304   }
268305 }