// bidwatcher // copyright (c) 1999-2005 // Trent McNair (trent@rmci.net) // Tom McNair (tmcnair@cyberhighway.net) // Wayne Schlitt (wayne@midwestcs.com) // Ben Byer (bushing@users.sourceforge.net) // Kevin Dwyer (kevin@pheared.net) // // use of this code is restricted to the terms // of the GNU GPL, which should have been included in this // distribution. If not, see www.gnu.org/copyleft/gpl.html. // Here is the short version: // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // #include "config.h" #include #include #include #include #include #include // Handle strict Ansi compliance with gcc 3.1 while retaining // backward compatibility. #ifdef HAVE_FSTREAM # include #else # ifdef HAVE_FSTREAM_H # include # endif #endif #ifdef HAVE_SSTREAM # include #else # ifdef HAVE_STRSTREAM_H # include # endif #endif #include #include #include #include #include #include #include "portability.h" #include "bidwatcher.h" #include "bidgroup.h" #include "bidgui.h" #include "pixmaps/user.xpm" #include "pixmaps/clock.xpm" #include "pixmaps/exit.xpm" #include "pixmaps/help.xpm" #include "pixmaps/update.xpm" #include "pixmaps/stop.xpm" #include "pixmaps/plus.xpm" #include "pixmaps/redled.xpm" #include "pixmaps/blueled.xpm" #include "pixmaps/blackled.xpm" #include "pixmaps/greenled.xpm" #include "pixmaps/arrow.xpm" #include "pixmaps/bidwatch.xpm" using namespace std; char *banner1 = "bidwatcher " VERSION " is GPL'd and has NO WARRANTY; " "press the ABOUT button for details"; char *banner2 = "Help us: please report ALL bugs at " "http://sourceforge.net/projects/bidwatcher"; const char *const bw_subdir = ".bidwatcher"; // This should probably get turned off for normal builds. // #define DEBUG_NETWORK bool dbug = FALSE; bool configOpen=FALSE; bool commentOpen=FALSE; bool addOpen=FALSE; bool helpOpen=FALSE; bool passOpen=FALSE; URL *proxyurl, *timesyncurl; GdkFont *fixed_font; GdkFont *clean14; int numbids; char authID[76]; char authPASS[76]; struct auctioninfo * auction[MAXAUCS+1]; enum { TARGET_URL }; static GtkTargetEntry target_table[] = { { "STRING", 0, TARGET_URL }, { "text/plain", 0, TARGET_URL }, { "text/uri-list", 0, TARGET_URL } }; static guint n_targets = sizeof(target_table) / sizeof(target_table[0]); /* Used to mark which button was pressed while changing colors */ static GtkWidget *button_pressed; GdkColor cyan={0,0,100*256,65535},red={0,200*256,0,0},blue={0,0,0,200*256}, green={0,0,240*256,0},black={0,0,0,0},yellow={0,200*256,200*256,0}, white={0,255,255,255}, peach={0,60000,60000,50000}, lightblue={0,59000,59000,60000}; GdkColor color_near={0,200*256,0,0}, color_far={0,0,0,0}, color_gone={0,0,100*256,65535}, color_win={0,0,0,0}, color_willwin={0,0,100*256,65535}, color_lose={0,200*256,0,0}, color_back1={0,59000,59000,60000}, color_back2={0,60000,60000,50000}, color_none={0,175*256,0,175*256}; #define NUMCOLORS 8 GdkColor *colors[NUMCOLORS] = {&color_far, &color_near, &color_gone, &color_win, &color_willwin, &color_lose, &color_back1, &color_back2}; GtkStyle *greenstyle, *redstyle, *yellowstyle, *clean14style; GtkStyle *wgreenstyle, *wredstyle, *wyellowstyle; GtkStyle *win_style, *willwin_style, *lose_style; GtkStyle *win_style2, *willwin_style2, *lose_style2; GtkStyle *clist_willwin1, *clist_win1, *clist_lose1; GtkStyle *clist_willwin2, *clist_win2, *clist_lose2; GtkTooltips *tooltips; GtkWidget *aucList, *servertimelabel, *statuswindow; GtkWidget *ebtime, *localtimelabel; int localtimeval = 0; int currentauc; GtkWidget *window, *userconfigMenu, *statuslabel=NULL, *statusbox; GtkWidget *userPMW, *plusPMW, *clockPMW, *updatePMW, *helpPMW, *exitPMW, *stopPMW, *userBut, *plusBut, *clockBut, *updateBut, *helpBut, *exitBut, *stopBut, *redled, *blueled, *greenled, *blackled, *errorbox, *errorstat, *addentry; GdkPixmap *redledPM, *redledmask, *blueledPM, *blueledmask, *greenledPM, *greenledmask, *blackledPM, *blackledmask, *arrowPM, *arrowmask; int aucIdx; volatile bool updateInProgress; bool firstRun; bool checkForSnipe; int Timer1Idx; int Timer2Idx; int timeDiff; int snipeDelay; int update_prio1_interval; int update_prio2_interval; int update_prio3_interval; int update_prio4_interval; int country; char proxystring[200]; char proxyuserstring[200]; char proxypassstring[200]; char browserPATH[200]; char emailPATH[200]; bool trackListings; bool trackBids; bool retain_location; bool retain_size; bool autoDelete; bool doStartup; bool soundOn; bool clockIsSet; int security; int window_x, window_y, window_height, window_width; int selection_id; char fixedFont[400], cleanFont[400]; guint errorcontext; ConfigWindow *confwindow; PopupMenu *popupmenu; CommentWindow *comwindow; gint errorstat_timeout; void DoEmail(char *name, char *auctionid); static void deleteitem_handler(GtkMenuItem *MenuItem, gpointer data); static void flush_handler(GtkMenuItem *MenuItem, gpointer data); static void updateitem_handler(GtkMenuItem *MenuItem, gpointer data); GtkWidget *makeicon(GtkWidget *toplevel, char **xpm); void die() { fprintf(stderr, "You've found a bug in bidwatcher! Please fill out a bug\n" "report, attaching the above output, at\n" "http://sourceforge.net/projects/bidwatcher/\n"); exit(0); } bool isValidAuction(long int auc) { if (currentauc < 0 || currentauc >= aucIdx) return FALSE; else return TRUE; } GtkStyle *get_style(struct auctioninfo *auc, int i) { /* This code needed to be in one spot, and correct. ;) -kdwyer */ /* We're now returning a real GtkStyle, and using the static ones. */ /* bid column color: (These will be configurable.) * green - I have bid and am the high bidder yellow - I will snipe and (afaik) will be the high bidder red - I have bid or will snipe, but am not / will not be the high bidder */ if (auc->myBidQuantity > 0) { if (!strcmp(auc->HighBidder, authID)) return (i % 2) ? clist_win2 : clist_win1; if ((auc->isSnipe && auc->myBidAmount >= auc->minBid())) return (i % 2) ? clist_willwin2 : clist_willwin1; } return (i % 2) ? clist_lose2 : clist_lose1; } void checkaucs(int line) { int i; for(i=0; iinfourl == NULL) { fprintf(stderr, "auction[%i]->infourl was invalid at %d\n", i, line); die(); } */ if (auction[i]->magic != 12345) { fprintf(stderr, "auction[%i]->magic was %d at %d\n", i, auction[i]->magic, line); die(); } } } #define CHECK checkaucs(__LINE__) // Thanks to Bob Beaty /* * getTimeStamp * Construct a current timestamp for us. * Returns a pointer to a static buffer. */ char *getTimeStamp() { static char timeBuff[20]; time_t now; struct tm *localnow; now = time(NULL); localnow = localtime(&now); memset(timeBuff, 0, sizeof timeBuff); // ANSI C99: %F %T strftime(timeBuff, sizeof timeBuff, "%Y-%m-%d %H:%M:%S", localnow); return timeBuff; } /* * showError * Displays an error message in the status bar. Prepends ERR_STRING. */ void showError(char *arg) { char *err; int len; len = strlen(ERR_STRING) + strlen(arg) + 1; err = (char *) malloc(len); snprintf(err, len, "%s%s", ERR_STRING, arg); DPRINTF(DLOW, ("ErrorArg: %s || ErrorPassed: %s\n", arg, err)); showBidStatus(err); } /* * showBidStatus * Displays a status message in the status bar. * All messages will get queued so that they may be viewed as they were * entered. */ void showBidStatus(char *arg) { char msg[MAX_STATUS_LEN]; sprintf(msg, "[%s] %s", getTimeStamp(), arg); printf("%s\n", msg); if (errorstat != NULL) { gtk_statusbar_push(GTK_STATUSBAR(errorstat), errorcontext, msg); } } /* * showStatus * This presents the status message in 'arg' to the user in the upper * status bar. */ void showStatus(char *arg) { // The statuslabel may not exist yet, in that case, // write to stdout. if (statuslabel) { // add a space on the front, if it's possible char *t = g_strdup_printf(" %s", arg); if (t == NULL) { gtk_label_set_text(GTK_LABEL(statuslabel), arg); } else { gtk_label_set_text(GTK_LABEL(statuslabel), t); g_free(t); } } else printf("Status: %s\n", arg); } void configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { if (event->send_event == 1) { // Change in location window_x = event->x; window_y = event->y; } else { // Change in size window_height = event->height; window_width = event->width; } } void greenLED(void) { gtk_pixmap_set(GTK_PIXMAP(blackled), greenledPM, greenledmask); } void blackLED(void) { gtk_pixmap_set(GTK_PIXMAP(blackled), blackledPM, blackledmask); } void timesync_callback(GtkWidget *widget, gpointer data) { if (updateInProgress) return; updateInProgress = TRUE; TimeSync(); updateInProgress = FALSE; } void cancel_callback(GtkWidget *widget, gpointer data) { cancelPressed = TRUE; } void exitwarnok_callback(GtkWidget *widget, gpointer data) { gtk_main_quit(); } void showExitWarning(gchar *message) { /* This let's us deliver a last ditch warning about the security * settings not storing the password. */ GtkWidget *window = gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window), 10); gtk_window_set_title(GTK_WINDOW(window), "Snipe Failure Warning"); gtk_widget_set_uposition(window, 200, 200); GtkWidget *messagelabel = gtk_label_new(message); gtk_widget_show(messagelabel); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), messagelabel, FALSE, FALSE, 0); GtkWidget *okbutton = gtk_button_new_with_label("Warning Acknowledged"); gtk_signal_connect(GTK_OBJECT(okbutton), "clicked", GTK_SIGNAL_FUNC(exitwarnok_callback), NULL); gtk_widget_show(okbutton); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton, FALSE, FALSE, 0); gtk_widget_show(window); } int numSnipes() { int count=0; for(int i=0; iisSnipe) count++; } return count; } void exit_callback(GtkWidget *widget, gpointer data) { if (updateInProgress == TRUE) return; WriteAucFile(); if ((security > SEC_LOW) && numSnipes()) showExitWarning("WARNING: Security setting will not store your password.\n" "You will have to reenter that information next time\n" "if you want your snipes to succeed."); else gtk_main_quit(); } void delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { exit_callback(NULL, NULL); } void destroy_event(GtkWidget *widget, gpointer data) { exit_callback(NULL, NULL); } void update_callback(GtkWidget *widget, gpointer data) { if (updateInProgress) return; updateInProgress = TRUE; int retval; if (strlen(authID) > 1) switch(retval = GetUserBids()) { case GUA_SUCCESS: GetUserListings(); UpdateList(); break; case GUA_BADUSER: showError("Update failed: Invalid username"); break; default: showError("Update failed: Network error"); DPRINTF(DHIGH, ("getuserbids2 returned %d\n", retval)); } if (aucIdx != 0) Update(-1, FALSE, TRUE); updateInProgress = FALSE; } static void detailsclose_callback(GtkWidget *widget, gpointer data) { DetailsWindow *obj = ((DetailsWindow *) data); gtk_widget_destroy(obj->window); } static void detailsdestroy_callback(GtkWidget *widget, gpointer data) { DetailsWindow *obj = ((DetailsWindow *) data); delete obj; } static void bidclose_callback(GtkWidget *widget, gpointer data) { BidWindow *obj = ((BidWindow *) data); gtk_widget_destroy(obj->window); } static void biddestroy_callback(GtkWidget *widget, gpointer data) { BidWindow *obj = ((BidWindow *) data); delete obj; } static void aboutclose_callback(GtkWidget *widget, gpointer data) { AboutWindow *obj = ((AboutWindow *) data); gtk_widget_destroy(obj->window); } static void aboutdestroy_callback(GtkWidget *widget, gpointer data) { AboutWindow *obj = ((AboutWindow *) data); delete obj; } static void endedclose_callback(GtkWidget *widget, gpointer data) { EndedWindow *obj = ((EndedWindow *) data); delete obj; } static void endedmonth_callback(GtkWidget *widget, gpointer data) { EndedWindow *obj = ((EndedWindow *) data); obj->iscurrent = !obj->iscurrent; obj->update(); } static void configclose_callback(GtkWidget *widget, gpointer data) { ConfigWindow *obj = ((ConfigWindow *) data); gtk_widget_destroy(obj->window); } static void configdestroy_callback(GtkWidget *widget, gpointer data) { ConfigWindow *obj = ((ConfigWindow *) data); delete obj; } static void color_dlg_cancel (GtkWidget *button, gpointer data) { gtk_widget_destroy(GTK_WIDGET(data)); } static void color_dlg_ok (GtkWidget *button, GtkWidget *color_dlg) { GdkColor *color; gdouble new_color[3]; GtkStyle *style; if (!GTK_IS_WIDGET (button_pressed)) { gtk_widget_destroy(color_dlg); return; } color = (GdkColor *)gtk_object_get_user_data(GTK_OBJECT(button_pressed)); gtk_color_selection_get_color((GtkColorSelection *) ((GtkColorSelectionDialog *) color_dlg)->colorsel, new_color); gdk_colormap_free_colors(gtk_widget_get_colormap (button_pressed), color, 1); color->red = (guint16) (new_color[0] * 65535.0); color->green = (guint16) (new_color[1] * 65535.0); color->blue = (guint16) (new_color[2] * 65535.0); color->pixel = (gulong) ((color->red & 0xff00) * 256 + (color->green & 0xff00) + (color->blue & 0xff00) / 256); gdk_color_alloc (gtk_widget_get_colormap(button), color); style = gtk_style_new(); style->bg[0] = *color; gtk_widget_set_style (button_pressed, style); gtk_style_unref (style); gtk_widget_destroy (color_dlg); } static void color_edit(GtkWidget *button, GdkColor *color) { GtkWidget *dialog; gdouble new_color[3]; new_color[0] = color->red / 65535.0; new_color[1] = color->green / 65535.0; new_color[2] = color->blue / 65535.0; dialog = gtk_color_selection_dialog_new ("Select color"); gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG (dialog)->help_button); gtk_signal_connect(GTK_OBJECT (((GtkColorSelectionDialog *) dialog)->ok_button), "clicked", GTK_SIGNAL_FUNC (color_dlg_ok), dialog); gtk_signal_connect(GTK_OBJECT (((GtkColorSelectionDialog *) dialog)->cancel_button), "clicked", GTK_SIGNAL_FUNC (color_dlg_cancel), dialog); gtk_widget_set_sensitive(((GtkColorSelectionDialog *) dialog)->help_button, FALSE); gtk_color_selection_set_color((GtkColorSelection *) ((GtkColorSelectionDialog *)dialog)->colorsel, new_color); gtk_widget_show(dialog); button_pressed = button; } static void errorclose_callback(GtkWidget *widget, gpointer data) { ErrorWindow *obj = ((ErrorWindow *) data); delete obj; } static void confirmclose_callback(GtkWidget *widget, gpointer data) { ConfirmWindow *obj = ((ConfirmWindow *) data); delete obj; } static void confirmok_callback(GtkWidget *widget, gpointer data) { flush(); ConfirmWindow *obj = ((ConfirmWindow *) data); delete obj; } int dosignin() { URL *bidurl; char *Buff; int returnVal; char *ustring, *vstring; char cookiejar[200]; memset(cookiejar, 0, sizeof cookiejar); snprintf(cookiejar, (sizeof cookiejar) - 1, "%s/%s/cookies.txt", getenv("HOME"), bw_subdir); /* Sign in First */ bidurl = new URL("http://signin.ebay.com/ws2/eBayISAPI.dll?SignIn", "", proxyurl); returnVal = fetchURL(bidurl, 0, &Buff, cookiejar, 2); free(Buff); Buff = NULL; delete(bidurl); ustring = g_strdup_printf("https://signin.ebay.com/ws/eBayISAPI.dll" "?co_partnerid=2&siteid=0&UsingSSL=1"); vstring = g_strdup_printf("MfcISAPICommand=SignInWelcome" "&siteid=0&co_partnerId=2&UsingSSL=1" "&ru=&pp=&pa1=&pa2=&pa3=&i1=-1&pageType=-1" "&userid=%s&pass=%s&keepMeSignInOption=1", authID, authPASS); bidurl = new URL(ustring, vstring, proxyurl); g_free(ustring); g_free(vstring); returnVal = fetchURL(bidurl, 1, &Buff, cookiejar, 0); free(Buff); Buff = NULL; delete(bidurl); return returnVal; } void auctioninfo::getkey(float bid, int quantity) { char *Buff; snipeAmount=bid; snipeQty=quantity; myBidAmount=bid; myBidQuantity=quantity; memset(snipeKey, 0, sizeof(snipeKey)); snipeKey[0] = '1'; //return; // rhe real work is done by eBayAgent //printf("myBidAmount set to %f\n",bid); int returnVal; char *ustring, *vstring; char cookiejar[200]; snprintf(cookiejar, (sizeof cookiejar) - 1, "%s/%s/cookies.txt", getenv("HOME"), bw_subdir); dosignin(); /* eBay has gotten pickier about URLs. If you don't specify * ebaymotors then you get some unknown error, yet the bid * still goes through. Go figure. * * Also, non-Dutch auctions don't have the quant variable set for the * key URL. This should change so we don't look suspicious. */ (AuctionType == TYPE_EBAYMOTORSCAR || AuctionType == TYPE_EBAYMOTORS) ? ustring = g_strdup_printf("http://cgi.ebay.com/ebaymotors/" "aw-cgi/eBayISAPI.dll" "?MfcISAPICommand=MakeBid" "&item="LLU_FMT"maxbid=%.2f&quant=%d", ItemNumber,bid,quantity) : ustring = g_strdup_printf("http://offer.ebay.com/" "ws/eBayISAPI.dll" "?MfcISAPICommand=MakeBid" "&item="LLU_FMT"&maxbid=%.2f&quant=%d", ItemNumber,bid,quantity); ustring = g_strdup_printf("http://offer.ebay.com/ws/eBayISAPI.dll"); vstring = g_strdup_printf("MfcISAPICommand=MakeBid&fp=2&co_partnerid=" "&item=%llu&maxbid=%.2f&quant=%d", ItemNumber,bid,quantity); bidurl = new URL(ustring, vstring, proxyurl); returnVal = fetchURL(bidurl, 1, &Buff, cookiejar, 0); if (returnVal != NET_SUCCESS) { if (returnVal == NET_NETERROR) showError("Could not obtain bid key: a network error occurred."); else if (returnVal == NET_TIMEOUT) showError("Network timeout error"); return; } char lineBuff[8000]; returnVal = ProcessBidSubmission(Buff, lineBuff, 8000); memset(snipeKey, 0, sizeof(snipeKey)); switch(returnVal) { case PBS_BIDTOOLOW: sprintf(lineBuff, "Pre-bid on "LLU_FMT" for %.2f FAILED: bid below asking price", ItemNumber, snipeAmount); break; case PBS_BADQUANTITY: sprintf(lineBuff, "Pre-bid on "LLU_FMT" FAILED: Bad quantity '%d'", ItemNumber, snipeQty); break; case PBS_AUCTIONOVER: sprintf(lineBuff, "Pre-bid on "LLU_FMT" FAILED: Auction already ended", ItemNumber); break; case PBS_PREAPPROVAL: sprintf(lineBuff, "Pre-bid on "LLU_FMT" FAILED: Need pre-approval", ItemNumber); break; case PBS_SUCCESS: // ok, eBay liked our bid submission so we can go ahead and make the bid char snipebuff[512]; char *keyptr; keyptr = strstr(lineBuff, "name=\"key\""); keyptr = strstr(keyptr, "value=\""); keyptr += strlen("value=\""); unsigned int x; for (x=0; *keyptr != '\"'; x++) { snipebuff[x] = *keyptr; keyptr++; } snipebuff[x] = 0; DPRINTF(DLOW, ("Snipe key is %s\n", snipebuff)); strcpy(snipeKey, snipebuff); sprintf(lineBuff, "Pre-bid on "LLU_FMT" SUCCEEDED: %d at %.2f", ItemNumber, snipeQty, snipeAmount); break; default: sprintf(lineBuff, "Pre-bid on "LLU_FMT" FAILED: Unable to determine error." " This indicates a bug.", ItemNumber); } showBidStatus(lineBuff); DPRINTF(DHIGH, ("%s\n", lineBuff)); free(Buff); } int auctioninfo::bid(bool windows) { //char exebuffer[200]; //sprintf(exebuffer, "eBayAgent -B -b %.2f "LLU_FMT, snipeAmount, ItemNumber); //fprintf(stderr, "bidding with %s\n", exebuffer); //system(exebuffer); //showBidStatus("bidding done using eBayAgent"); //return bidstatus = NET_SUCCESS; char *Buff; char lineBuff[1024]; int returnVal, retval; char cookiejar[200]; snprintf(cookiejar, (sizeof cookiejar) - 1, "%s/%s/cookies.txt", getenv("HOME"), bw_subdir); sprintf(bidurl->fullurlpost, "MfcISAPICommand=MakeBid&item="LLU_FMT"&key=%s" "&user=%s&pass=%s&maxbid=%.2f&quant=%d" "&acceptbinbid=0&mode=1&userid=default&javascriptenabled=1", ItemNumber, snipeKey, authID, authPASS, snipeAmount, snipeQty); DPRINTF(DHIGH, ("Bid(%s?%s)\n", bidurl->fullurl, bidurl->fullurlpost)); retval = fetchURL(bidurl, 1, &Buff, cookiejar, 0); if (retval != NET_SUCCESS) { sprintf(lineBuff,"Bid on "LLU_FMT" FAILED: Error %d connecting to eBay", ItemNumber, retval); showBidStatus(lineBuff); free(Buff); return INFO_NETERROR; } returnVal = ProcessBid(Buff); windows = TRUE; updateitem(ItemNumber); if (windows && retval == PBS_SUCCESS) { switch(returnVal) { case PB_HIGHBID: sprintf(lineBuff,"Bid on "LLU_FMT" SUCCEEDED: You are the high bidder", ItemNumber); break; case PB_OUTBID: sprintf(lineBuff,"Bid on "LLU_FMT" LOST: Someone has outbid you", ItemNumber); break; case PB_BIDTOOLOW: sprintf(lineBuff,"Bid on "LLU_FMT" FAILED: Bid below current asking price", ItemNumber); break; case PB_BADQUANTITY: sprintf(lineBuff,"Bid on "LLU_FMT" FAILED: Bad quantity '%d'", ItemNumber,snipeQty); break; case PB_AUCTIONOVER: sprintf(lineBuff,"Bid on "LLU_FMT" FAILED: Auction already ended", ItemNumber); break; case PB_BADUSER: sprintf(lineBuff,"Bid on "LLU_FMT" FAILED: Invalid username or password!", ItemNumber); break; default: sprintf(lineBuff,"Bid on "LLU_FMT" FAILED: Unable to determine error." " This indicates a bug.", ItemNumber); char *fnstring; fnstring = g_strdup_printf("%s/%s/error-"LLU_FMT".html", getenv("HOME"), bw_subdir,ItemNumber); FILE *erfile=fopen(fnstring, "w"); //fprintf(erfile,"Error: could not parse answer.\n%s\n",bidurl->url); fprintf(erfile,"%s",Buff); fclose(erfile); g_free(fnstring); break; } showBidStatus(lineBuff); bidstatus=returnVal; free(Buff); return retval; } free(Buff); return ERROR; } void bidengine(BidWindow *obj, int auc, bool doSnipe) { int returnVal; gtk_widget_set_sensitive(obj->okbutton, FALSE); gtk_widget_set_sensitive(obj->cancelbutton, FALSE); gtk_label_set_text(GTK_LABEL(obj->currentbidlabel), "Obtaining key..."); setBid(obj->myauc, atof(gtk_entry_get_text(GTK_ENTRY(obj->bidtext))), atoi(gtk_entry_get_text(GTK_ENTRY(obj->quantitytext))), doSnipe, false ); gtk_widget_set_sensitive(obj->okbutton, TRUE); gtk_widget_set_sensitive(obj->cancelbutton, TRUE); gtk_label_set_text(GTK_LABEL(obj->currentbidlabel), ""); if (doSnipe) { gtk_widget_set_sensitive(obj->okbutton, TRUE); gtk_widget_set_sensitive(obj->cancelbutton, TRUE); gtk_label_set_text(GTK_LABEL(obj->currentbidlabel), ""); setupSnipe(obj->myauc, auc); return; } else { // Don't do any bidding if the key setup failed if (obj->myauc->snipeKey[0] == '\0') return; gtk_label_set_text(GTK_LABEL(obj->currentbidlabel), "Submitting bid..."); // now, finalize bid with the key obtained. char WebPage[255]; returnVal = obj->myauc->bid(true); switch(returnVal) { case NET_NETERROR: showError("Could not obtain key: a network error occurred."); break; case NET_TIMEOUT: showError("Could not obtain key: Network timeout error"); break; case NET_SUCCESS: sprintf(WebPage, "Current Bid : %.2f", obj->myauc->CurrentBid); switch(obj->myauc->reserveMet) { case 'y': strcat(WebPage, " - reserve met"); break; case 'n': strcat(WebPage, " - reserve not met"); break; case 'x': strcat(WebPage, " - no reserve"); break; case 'b': strcat(WebPage, " - BuyItNow Only"); } // set the bid text if the network update returned success gtk_label_set_text(GTK_LABEL(obj->currentbidlabel), WebPage); return; default: // *shrug* showError("Could not obtain key: Unknown error"); break; } gtk_widget_set_sensitive(obj->okbutton, TRUE); gtk_widget_set_sensitive(obj->cancelbutton, TRUE); gtk_label_set_text(GTK_LABEL(obj->currentbidlabel), ""); updateitem_handler(NULL, NULL); } } void bidnow_callback(GtkWidget *widget, gpointer data) { int auc = currentauc; // So we don't get confused later. BidWindow *obj = (BidWindow *)data; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(obj->radio_bid))) { /* Make sure we have a password ready */ if (authPASS[0] == '\0') { if (!passOpen) new GetPass(); } else { /* Bid Now */ bidengine(obj, auc, FALSE); updateitem(obj->myauc->ItemNumber); gtk_widget_destroy(obj->window); } } else { if (security != SEC_HIGH) { if (authPASS[0] == '\0') { if (!passOpen) new GetPass(); } else { /* Snipe */ bidengine(obj, auc, TRUE); gtk_widget_destroy(obj->window); } } else { showError("Cannot snipe with security set on High. " "Choose Medium or Low."); gtk_widget_destroy(obj->window); } } /* Forget the user/password for High security */ if (security == SEC_HIGH) { memset(authID, 0, sizeof(authID)); memset(authPASS, 0, sizeof(authPASS)); } } int find_auction_index(unsigned long long aucnum) { // Locate the auction in the array of auctions for(int i=0; iItemNumber == aucnum) return i; } return -1; } int find_auction_index(struct auctioninfo *auc) { return find_auction_index(auc->ItemNumber); } struct auctioninfo *find_auction(unsigned long long aucnum) { int idx = find_auction_index(aucnum); if(idx < 0) return NULL; return auction[idx]; } void commentok_callback(GtkWidget *widget, gpointer data) { // Set the comment text into the auction struct CommentWindow *obj = (CommentWindow *)data; char bufn[COMMENT_LENGTH+1]; // Can't step on buf char *buf = gtk_editable_get_chars(GTK_EDITABLE(obj->text), 0, -1); STRNZCPY(bufn, buf); strip_newlines(bufn); snprintf(obj->myauc->Comments, sizeof(obj->myauc->Comments), "%s", bufn); UpdateListItem(find_auction_index(obj->myauc->ItemNumber)); gtk_widget_destroy(obj->window); } static void commentclose_callback(GtkWidget *widget, gpointer data) { CommentWindow *obj = ((CommentWindow *) data); gtk_widget_destroy(obj->window); } static void commentdestroy_callback(GtkWidget *widget, gpointer data) { CommentWindow *obj = ((CommentWindow *) data); delete obj; } gint detailstimer_callback(gpointer data) { DetailsWindow *obj = (DetailsWindow *)data; obj->update(); return TRUE; } /* static void detailsbidder_callback(GtkWidget *widget, gpointer data) { DetailsWindow * obj=((DetailsWindow *) data); DoEmail(obj->myauc->HighBidder,obj->myauc->ItemNumber); delete obj; } static void detailsseller_callback(GtkWidget *widget, gpointer data) { DetailsWindow * obj=((DetailsWindow *) data); DoEmail(obj->myauc->Seller,obj->myauc->ItemNumber); delete obj; } void DoEmail(char * name, char * auctionid) { char cookiejar[200]; snprintf(cookiejar, (sizeof cookiejar) - 1, "%s/%s/cookies.txt", getenv("HOME"), bw_subdir); if (strlen(name) < 2) { showError("No name to look up"); return; } else if ((strlen(authID) < 2) || (strlen(authPASS) < 2)) { showError("Username or password is required but missing"); return; } else if (name[0] == '-') return; else if (strcmp("Dutch Auction", name) == 0) return; else if (strstr(name,"@") != NULL) { CmEmail(name); return; } else { // if we made it here, we need to call up ebay and get // the email address. char *Buff; char *Buff2; char WebPage[250]; sprintf(WebPage,"http://contact.ebay.com/aw-cgi/eBayISAPI.dll?" "ReturnUserEmail&requested=%s&userid=%s&pass=%s&iid=%s", name,authID,authPASS,auctionid); URL *emailurl=new URL(WebPage, "", proxyurl); int err = fetchURL(emailurl, 0, &Buff, cookiejar, 0); delete(emailurl); if ((err == NET_NETERROR) || (err == NET_TIMEOUT) || (strlen(Buff) < 1000)) { showError("Could not get email address: Network error"); return; } Buff2=StripHtmlTags(Buff); int returnVal = ParseEmailAddress(Buff2, name); free(Buff); free(Buff2); switch(returnVal) { case PEA_SUCCESS: CmEmail(name); break; case PEA_BADUSER: showError("Could not get email address: bad password"); break; default: showError("Could not get email address: Unknown error"); break; } } } */ void toggle_button_callback (GtkWidget *widget, gpointer data) { *((bool *)data) = GTK_TOGGLE_BUTTON (widget)->active; } void toggle_localtime(GtkWidget *widget, gpointer data) { // Change the mod value if we get more options localtimeval = (localtimeval + 1) % 3; } void getpassok_callback (GtkWidget *widget, gpointer data) { GetPass * obj=((GetPass *) data); char encpassword[76]; strcpy(authID, gtk_entry_get_text(GTK_ENTRY(obj->useridentry))); encode_password(encpassword, gtk_entry_get_text(GTK_ENTRY(obj->passentry))); strcpy(authPASS, encpassword); gtk_widget_destroy(obj->window); } void getpassclose_callback (GtkWidget *widget, gpointer data) { GetPass *obj = ((GetPass *) data); gtk_widget_destroy(obj->window); } static void getpassdestroy_callback(GtkWidget *widget, gpointer data) { GetPass *obj = ((GetPass *) data); delete obj; } void configok_callback (GtkWidget *widget, gpointer data) { char encpassword[76]; snipeDelay = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON (confwindow-> snipespin)); update_prio1_interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON (confwindow-> update_prio1_spin)); update_prio2_interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON (confwindow-> update_prio2_spin)); update_prio3_interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON (confwindow-> update_prio3_spin)); update_prio4_interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON (confwindow-> update_prio4_spin)); GtkOptionMenu *omenu; GtkMenu *intlmenu; GtkWidget *active; omenu = GTK_OPTION_MENU(confwindow->country_option); intlmenu = GTK_MENU(gtk_option_menu_get_menu(omenu)); active = gtk_menu_get_active(intlmenu); country = g_list_index(GTK_MENU_SHELL(intlmenu)->children, active); strcpy(authID, gtk_entry_get_text(GTK_ENTRY(confwindow->useridtext))); encode_password(encpassword, gtk_entry_get_text(GTK_ENTRY(confwindow->passwordtext))); strcpy(authPASS,encpassword); strcpy(browserPATH, gtk_entry_get_text(GTK_ENTRY(confwindow->browsertext))); strcpy(emailPATH, gtk_entry_get_text(GTK_ENTRY(confwindow->mailclienttext))); strcpy(proxystring,gtk_entry_get_text(GTK_ENTRY(confwindow->proxytext))); strcpy(proxyuserstring, gtk_entry_get_text(GTK_ENTRY(confwindow->proxyusertext))); strcpy(proxypassstring, gtk_entry_get_text(GTK_ENTRY(confwindow->proxypasstext))); strcpy(fixedFont, gtk_entry_get_text(GTK_ENTRY(confwindow->fixed_font_text))); //gdk_font_unref(fixed_font); fixed_font = gdk_font_load(fixedFont); if (!fixed_font) { gdk_font_load(FONT_FIX_DFL); strcpy(fixedFont, FONT_FIX_DFL); } strcpy(cleanFont, gtk_entry_get_text(GTK_ENTRY(confwindow->clean_font_text))); //gdk_font_unref(clean14); clean14 = gdk_font_load(cleanFont); if (!clean14) { gdk_font_load(FONT_CLEAN_DFL); strcpy(cleanFont, FONT_CLEAN_DFL); } makeStyles(); resetStyles(); trackListings = confwindow->listing; trackBids = confwindow->bid; doStartup = confwindow->startup; autoDelete = confwindow->del; retain_location = confwindow->location; retain_size = confwindow->size; if (proxyurl != NULL) delete(proxyurl); if (strlen(proxystring) > 2) { char *pxy = g_strdup_printf("http://%s/",proxystring); proxyurl = new URL(pxy, "", NULL, proxyuserstring, proxypassstring); g_free(pxy); } else proxyurl = NULL; resetTimeSyncURL(); /* Set security level */ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(confwindow->radio_sec_low))) security=SEC_LOW; else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(confwindow->radio_sec_medium))) security=SEC_MED; else { security=SEC_HIGH; /* Forget the user/password for High security */ memset(authID, 0, sizeof(authID)); memset(authPASS, 0, sizeof(authPASS)); } WriteAucFile(); gtk_widget_destroy(confwindow->window); } ConfigWindow::ConfigWindow() { window = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(window), "Bidwatcher Configuration"); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); notebook = gtk_notebook_new(); bookbox[CONFIG_MAIN] = gtk_vbox_new(FALSE, 0); bookbox[CONFIG_COLOR] = gtk_vbox_new(FALSE, 0); bookbox[CONFIG_FONT] = gtk_vbox_new(FALSE, 0); gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE); /* CONFIG_MAIN */ user_frame = gtk_frame_new("User Information"); sys_frame = gtk_frame_new("System Information"); toggle_frame = gtk_frame_new("Auction Options"); useridlabel = gtk_label_new("Enter user ID:"); passwordlabel = gtk_label_new("Enter password:"); browserlabel = gtk_label_new("Path to web browser:"); mailclientlabel = gtk_label_new("Path to email client:"); proxylabel = gtk_label_new("Proxy server:"); proxyuserlabel = gtk_label_new("Proxy username:"); proxypasslabel = gtk_label_new("Proxy password:"); proxyusertext = gtk_entry_new(); proxypasstext = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(proxypasstext), FALSE); useridtext = gtk_entry_new(); passwordtext = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(passwordtext), FALSE); browsertext = gtk_entry_new(); mailclienttext = gtk_entry_new(); proxytext = gtk_entry_new(); listingcheck = gtk_check_button_new_with_label("Track my eBay listings"); bidcheck = gtk_check_button_new_with_label("Track current bids"); startupcheck = gtk_check_button_new_with_label("Check auctions on startup"); deletecheck = gtk_check_button_new_with_label("Automatically delete ended " "auctions"); location_check = gtk_check_button_new_with_label("Retain window position"); size_check = gtk_check_button_new_with_label("Retain window size"); label_security = gtk_label_new("Security level:"); radio_sec_low = gtk_radio_button_new_with_label(NULL, "Low"); radio_sec_medium = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(radio_sec_low)), "Medium"); radio_sec_high = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(radio_sec_low)), "High"); snipeadj = gtk_adjustment_new(snipeDelay, 1, 1000, 1, 10, 10); snipespin = gtk_spin_button_new(GTK_ADJUSTMENT(snipeadj), 1.0, 0); snipelabel = gtk_label_new("Snipe timer"); snipebox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(snipebox), snipespin, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(snipebox), snipelabel, FALSE, FALSE, 0); update_prio1_adj = gtk_adjustment_new(update_prio1_interval, 1, 1000, 1, 10, 10); update_prio1_spin = gtk_spin_button_new(GTK_ADJUSTMENT(update_prio1_adj), 1.0, 0); update_prio1_label = gtk_label_new("Update interval (<3mins)"); update_prio1_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio1_box), update_prio1_spin, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio1_box), update_prio1_label, FALSE, FALSE, 0); update_prio2_adj = gtk_adjustment_new(update_prio2_interval, 1, 1000, 1, 10, 10); update_prio2_spin = gtk_spin_button_new(GTK_ADJUSTMENT(update_prio2_adj), 1.0, 0); update_prio2_label = gtk_label_new("Update interval (<15mins)"); update_prio2_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio2_box), update_prio2_spin, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio2_box), update_prio2_label, FALSE, FALSE, 0); update_prio3_adj = gtk_adjustment_new(update_prio3_interval, 1, 1000, 1, 10, 10); update_prio3_spin = gtk_spin_button_new(GTK_ADJUSTMENT(update_prio3_adj), 1.0, 0); update_prio3_label = gtk_label_new("Update interval (<120mins)"); update_prio3_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio3_box), update_prio3_spin, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio3_box), update_prio3_label, FALSE, FALSE, 0); update_prio4_adj = gtk_adjustment_new(update_prio4_interval, 1, 1000, 1, 10, 10); update_prio4_spin = gtk_spin_button_new(GTK_ADJUSTMENT(update_prio4_adj), 1.0, 0); update_prio4_label = gtk_label_new("Update interval (>120mins)"); update_prio4_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio4_box), update_prio4_spin, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(update_prio4_box), update_prio4_label, FALSE, FALSE, 0); /* Choose your ebay site */ country_box = gtk_hbox_new (FALSE, 0); gtk_widget_ref (country_box); gtk_object_set_data_full (GTK_OBJECT (bookbox[CONFIG_MAIN]), "country_box", country_box, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (country_box); country_label = gtk_label_new ("eBay Country:"); gtk_widget_ref (country_label); gtk_object_set_data_full (GTK_OBJECT (bookbox[CONFIG_MAIN]), "country_label", country_label, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (country_label); gtk_box_pack_start (GTK_BOX (country_box), country_label, FALSE, FALSE, 0); country_option = gtk_option_menu_new (); gtk_widget_ref (country_option); gtk_object_set_data_full (GTK_OBJECT (bookbox[CONFIG_MAIN]), "country_option", country_option, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (country_option); gtk_box_pack_start (GTK_BOX (country_box), country_option, TRUE, FALSE, 0); country_option_menu = gtk_menu_new (); glade_menuitem = gtk_menu_item_new_with_label ("USA"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Germany"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("UK"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Canada"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Australia"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Italy"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("France"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Netherlands"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Belgium"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Switzerland"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Austria"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Spain"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("New Zealand"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); glade_menuitem = gtk_menu_item_new_with_label ("Singapore"); gtk_widget_show (glade_menuitem); gtk_menu_append (GTK_MENU (country_option_menu), glade_menuitem); gtk_option_menu_set_menu (GTK_OPTION_MENU (country_option), country_option_menu); gtk_option_menu_set_history(GTK_OPTION_MENU(country_option), country); /* User Information */ usertable = gtk_table_new(2, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(usertable), 3); gtk_table_set_col_spacings(GTK_TABLE(usertable), 17); gtk_table_attach(GTK_TABLE(usertable), useridlabel, 0, 1, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(useridlabel), 0, 0.5); gtk_table_attach(GTK_TABLE(usertable), useridtext, 1, 2, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(usertable), passwordlabel, 0, 1, 1, 2, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(passwordlabel), 0, 0.5); gtk_table_attach(GTK_TABLE(usertable), passwordtext, 1, 2, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_container_add(GTK_CONTAINER(user_frame), usertable); systable = gtk_table_new(3, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(systable), 3); gtk_table_set_col_spacings(GTK_TABLE(systable), 3); gtk_table_attach(GTK_TABLE(systable), browserlabel, 0, 1, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(browserlabel), 0, 0.5); gtk_table_attach(GTK_TABLE(systable), browsertext, 1, 2, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(systable), mailclientlabel, 0, 1, 1, 2, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(mailclientlabel), 0, 0.5); gtk_table_attach(GTK_TABLE(systable), mailclienttext, 1, 2, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(systable), proxylabel, 0, 1, 2, 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(proxylabel), 0, 0.5); gtk_table_attach(GTK_TABLE(systable), proxytext, 1, 2, 2, 3, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(systable), proxyuserlabel, 0, 2, 3, 4, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(proxyuserlabel), 0, 0.5); gtk_table_attach(GTK_TABLE(systable), proxyusertext, 1, 2, 3, 4, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(systable), proxypasslabel, 0, 2, 4, 5, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(proxypasslabel), 0, 0.5); gtk_table_attach(GTK_TABLE(systable), proxypasstext, 1, 2, 4, 5, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_container_add(GTK_CONTAINER(sys_frame), systable); /* Auction Options */ toggletable = gtk_table_new(7, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(toggletable), 3); gtk_table_set_col_spacings(GTK_TABLE(toggletable), 3); gtk_table_attach(GTK_TABLE(toggletable), listingcheck, 0, 1, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), bidcheck, 0, 1, 1, 2, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), startupcheck, 1, 2, 1, 2, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), deletecheck, 1, 2, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), size_check, 0, 1, 2, 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), location_check, 1, 2, 2, 3, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), label_security, 0, 1, 3, 4, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); security_box = gtk_hbox_new(FALSE, FALSE); gtk_box_pack_start(GTK_BOX(security_box), radio_sec_low, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(security_box), radio_sec_medium, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(security_box), radio_sec_high, FALSE, FALSE, 0); gtk_table_attach(GTK_TABLE(toggletable), security_box, 1, 2, 3, 4, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), snipebox, 0, 1, 4, 5, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), update_prio1_box, 1, 2, 4, 5, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), update_prio2_box, 0, 1, 5, 6, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), update_prio3_box, 1, 2, 5, 6, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(toggletable), update_prio4_box, 0, 1, 6, 7, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE (toggletable), country_box, 1, 2, 6, 7, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 0); gtk_container_add(GTK_CONTAINER(toggle_frame), toggletable); gtk_box_pack_start(GTK_BOX(bookbox[CONFIG_MAIN]), user_frame, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(bookbox[CONFIG_MAIN]), sys_frame, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(bookbox[CONFIG_MAIN]), toggle_frame, FALSE, FALSE, 0); configOpen = TRUE; char plainpassword[76]; decode_password(plainpassword, authPASS); gtk_entry_set_text(GTK_ENTRY(useridtext), authID); gtk_entry_set_text(GTK_ENTRY(passwordtext), plainpassword); gtk_entry_set_text(GTK_ENTRY(browsertext), browserPATH); gtk_entry_set_text(GTK_ENTRY(mailclienttext), emailPATH); gtk_entry_set_text(GTK_ENTRY(proxytext), proxystring); gtk_entry_set_text(GTK_ENTRY(proxyusertext), proxyuserstring); gtk_entry_set_text(GTK_ENTRY(proxypasstext), proxypassstring); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(listingcheck), listing = trackListings); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bidcheck), bid = trackBids); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startupcheck), startup = doStartup); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(deletecheck), del = autoDelete); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(location_check), location = retain_location); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(size_check), size = retain_size); /* Toggle the current security level */ switch(security) { case SEC_LOW: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_sec_low), TRUE); break; case SEC_MED: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_sec_medium), TRUE); break; case SEC_HIGH: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_sec_high), TRUE); } gtk_signal_connect (GTK_OBJECT (listingcheck), "toggled", GTK_SIGNAL_FUNC (toggle_button_callback), (gpointer) &listing); gtk_signal_connect (GTK_OBJECT (bidcheck), "toggled", GTK_SIGNAL_FUNC (toggle_button_callback), (gpointer) &bid); gtk_signal_connect (GTK_OBJECT (startupcheck), "toggled", GTK_SIGNAL_FUNC (toggle_button_callback), (gpointer) &startup); gtk_signal_connect (GTK_OBJECT (deletecheck), "toggled", GTK_SIGNAL_FUNC (toggle_button_callback), (gpointer) &del); gtk_signal_connect (GTK_OBJECT (location_check), "toggled", GTK_SIGNAL_FUNC (toggle_button_callback), (gpointer) &location); gtk_signal_connect (GTK_OBJECT (size_check), "toggled", GTK_SIGNAL_FUNC (toggle_button_callback), (gpointer) &size); tab_label[CONFIG_MAIN] = gtk_label_new("Main"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), bookbox[CONFIG_MAIN], tab_label[CONFIG_MAIN]); /* CONFIG_COLOR */ color_ended_box = gtk_vbox_new(FALSE, FALSE); for (int x = 0; x < NUMCOLORS; x++) { color_button_style = gtk_style_new (); color_button_style->bg[0] = *colors[x]; switch (x) { case 0: color_button = gtk_button_new_with_label ("Color_far"); break; case 1: color_button = gtk_button_new_with_label ("Color_near"); break; case 2: color_button = gtk_button_new_with_label ("Color_gone"); break; case 3: color_button = gtk_button_new_with_label ("Bid/Snipe: Color_win"); break; case 4: color_button = gtk_button_new_with_label ("Bid/Snipe: Color_willwin"); break; case 5: color_button = gtk_button_new_with_label ("Bid/Snipe: Color_lose"); break; case 6: color_button = gtk_button_new_with_label ("Color_back1"); break; case 7: color_button = gtk_button_new_with_label ("Color_back2"); break; } gtk_object_set_user_data (GTK_OBJECT (color_button), colors[x]); gtk_container_add (GTK_CONTAINER (color_ended_box), color_button); gtk_signal_connect (GTK_OBJECT (color_button), "clicked", GTK_SIGNAL_FUNC (color_edit), colors[x]); gtk_widget_set_usize (color_button, 150, 0); gtk_widget_set_style (color_button, color_button_style); gtk_widget_show (color_button); gtk_style_unref (color_button_style); } gtk_box_pack_start(GTK_BOX(bookbox[CONFIG_COLOR]), color_ended_box, FALSE, FALSE, 0); tab_label[CONFIG_COLOR] = gtk_label_new("Colors"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), bookbox[CONFIG_COLOR], tab_label[CONFIG_COLOR]); /* CONFIG_FONT */ font_frame = gtk_frame_new("Font Selection"); fixed_font_label = gtk_label_new("Time font:"); clean_font_label = gtk_label_new("Auction list font:"); fixed_font_text = gtk_entry_new(); clean_font_text = gtk_entry_new(); if (fixedFont[0] != '\0') gtk_entry_set_text(GTK_ENTRY(fixed_font_text), fixedFont); else gtk_entry_set_text(GTK_ENTRY(fixed_font_text), FONT_FIX_DFL); if (cleanFont[0] != '\0') gtk_entry_set_text(GTK_ENTRY(clean_font_text), cleanFont); else gtk_entry_set_text(GTK_ENTRY(clean_font_text), FONT_CLEAN_DFL); font_table = gtk_table_new(2, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(font_table), 3); gtk_table_set_col_spacings(GTK_TABLE(font_table), 17); gtk_table_attach(GTK_TABLE(font_table), fixed_font_label, 0, 1, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(fixed_font_label), 0, 0.5); gtk_table_attach(GTK_TABLE(font_table), fixed_font_text, 1, 2, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(font_table), clean_font_label, 0, 1, 1, 2, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment(GTK_MISC(clean_font_label), 0, 0.5); gtk_table_attach(GTK_TABLE(font_table), clean_font_text, 1, 2, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_container_add(GTK_CONTAINER(font_frame), font_table); gtk_box_pack_start(GTK_BOX(bookbox[CONFIG_FONT]), font_frame, FALSE, FALSE, 0); tab_label[CONFIG_FONT] = gtk_label_new("Fonts"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), bookbox[CONFIG_FONT], tab_label[CONFIG_FONT]); /* Action area */ okbutton = gtk_button_new_with_label("OK"); cancelbutton = gtk_button_new_with_label("Cancel"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton,FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), cancelbutton,FALSE,FALSE,0); gtk_signal_connect (GTK_OBJECT (cancelbutton), "clicked", GTK_SIGNAL_FUNC (configclose_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", GTK_SIGNAL_FUNC (configok_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (configdestroy_callback), (gpointer) this); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), notebook, FALSE, FALSE, 0); gtk_widget_show_all(window); } ConfigWindow::~ConfigWindow() { configOpen = FALSE; UpdateList(); if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); } AboutWindow::AboutWindow() { window = gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window), 10); aboutlabel= gtk_label_new( "Bidwatcher [ v" VERSION " ]\n\n" "Original Authors: \n" "Trent McNair ,\n" "Tom McNair \n" "\n" "Current developers:\n" "Kevin Dwyer \n" "Jan Starzynski \n" "\n" "Previous developers:\n" "Wayne Schlitt \n" "Larry Gilbert (dischead@users.sourceforge.net)\n" "Ben Byer \n" "\n" "All copyrights under the GNU GPL 1998-2004.\n" "See the enclosed file COPYING for more details, or\n" "go to http://www.gnu.org/copyleft/gpl.html\n" "\n" "This software comes with ABSOLUTELY NO WARRANTY - \n" "please see sections 11 and 12 in the GNU GPL for details\n" "Submit all questions, bug reports, etc. " "to the forums at\n" "http://sourceforge.net/projects/bidwatcher\n" "\n" "For complete documentation, see the web pages that came\n" "with Bidwatcher, or view them at: \n" "http://bidwatcher.sourceforge.net" ); gtk_label_set_justify(GTK_LABEL(aboutlabel),GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), aboutlabel,FALSE,FALSE,0); okbutton=gtk_button_new_with_label("OK"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton,FALSE,FALSE,0); gtk_widget_show(aboutlabel); gtk_widget_show(okbutton); gtk_widget_show(window); gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", GTK_SIGNAL_FUNC (aboutclose_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (aboutdestroy_callback), (gpointer) this); helpOpen=TRUE; } AboutWindow::~AboutWindow() { helpOpen=FALSE; if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); } GetPass::GetPass() { window=gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window),10); missinglabel = gtk_label_new("Enter the missing information:"); useridlabel = gtk_label_new("UserID:"); passlabel = gtk_label_new("Password:"); useridentry = gtk_entry_new(); passentry = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(passentry), FALSE); gtk_entry_set_text(GTK_ENTRY(useridentry), authID); useridbox = gtk_hbox_new(FALSE, FALSE); passbox = gtk_hbox_new(FALSE, FALSE); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), missinglabel,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(useridbox), useridlabel,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(passbox), passlabel,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(useridbox), useridentry,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(passbox), passentry,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), useridbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), passbox,FALSE,FALSE,0); okbutton=gtk_button_new_with_label("OK"); cancelbutton=gtk_button_new_with_label("Cancel"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), cancelbutton,FALSE,FALSE,0); gtk_widget_show_all(window); gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", GTK_SIGNAL_FUNC (getpassok_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (cancelbutton), "clicked", GTK_SIGNAL_FUNC (getpassclose_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (getpassdestroy_callback), (gpointer) this); passOpen=TRUE; } GetPass::~GetPass() { passOpen=FALSE; if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); } DetailsWindow::DetailsWindow(struct auctioninfo * auc) { window=gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window),10); myauc=auc; currentbidlabel=gtk_label_new(""); gtk_widget_show(currentbidlabel); categorylabel=gtk_label_new(""); infolabel=gtk_label_new(""); hbox=gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),categorylabel,FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(hbox),infolabel,FALSE,FALSE,0); gtk_label_set_justify(GTK_LABEL(categorylabel),GTK_JUSTIFY_RIGHT); gtk_label_set_justify(GTK_LABEL(infolabel),GTK_JUSTIFY_LEFT); gtk_widget_show(categorylabel); gtk_widget_show(infolabel); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),currentbidlabel, FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->vbox),hbox,FALSE,FALSE,0); /* sellerbutton=gtk_button_new_with_label("mail seller"); bidderbutton=gtk_button_new_with_label("mail bidder"); */ cancelbutton=gtk_button_new_with_label("Close"); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), cancelbutton,FALSE,FALSE,0); /* gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), sellerbutton,FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), bidderbutton,FALSE,FALSE,0); */ // gtk_widget_show(sellerbutton); gtk_widget_show(bidderbutton); gtk_widget_show(cancelbutton); gtk_widget_show(window); gtk_signal_connect (GTK_OBJECT (cancelbutton), "clicked", GTK_SIGNAL_FUNC (detailsclose_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (detailsdestroy_callback), (gpointer) this); /* gtk_signal_connect (GTK_OBJECT (bidderbutton), "clicked", GTK_SIGNAL_FUNC (detailsbidder_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT (sellerbutton), "clicked", GTK_SIGNAL_FUNC (detailsseller_callback), (gpointer) this); */ fill(); } void DetailsWindow::fill() { gtk_label_set_text(GTK_LABEL(categorylabel), "\nSeller :\n" "Location :\n" "Ends :\n" "Ends (Local) :\n" "Time Left :\n" "Quantity :\n" "Number of Bids :\n" "High Bidder :\n" "Minimum Bid :\n" "First Bid :\n" "BuyitNow :\n" "Shipping 1:\n" "Shipping 2:\n" "Shipping 3:\n" "Snipe Amount :\n" ); char info[256]; DPRINTF(DLOW, ("myauc->CurrentBid == %.2f\n", myauc->CurrentBid)); sprintf(info, "Item Number : "LLU_FMT, myauc->ItemNumber); gtk_window_set_title(GTK_WINDOW(window), info); strcpy(info, "Current Bid : "); strcat(info, myauc->currency); char *cbid = g_strdup_printf("%.2f", myauc->CurrentBid); strcat(info, cbid); g_free(cbid); switch(myauc->reserveMet) { case 'y': strcat(info, " - reserve met"); break; case 'n': strcat(info, " - reserve not met"); break; case 'x': strcat(info, " - no reserve"); break; case 'b': strcat(info, " - BuyItNow Only"); break; } gtk_label_set_text(GTK_LABEL(currentbidlabel), info); update(); timeouttag = gtk_timeout_add(1000, detailstimer_callback, this); } void DetailsWindow::update() { char info[600]; char temp[20]; char temp2[30]; char unitstring[15]; strcpy(unitstring, " unit at "); // DBS if (myauc->snipeQty >= 2) // DBS strcpy(unitstring, " units at "); // DBS sprintf(temp, "%.2f", myauc->minBid()); char *quant, *bidc; strcpy(info, " "); strcat(info, myauc->Seller); strcat(info, myauc->SellerRate); strcat(info, "\n "); strcat(info, myauc->Location); strcat(info, "\n "); strcat(info, myauc->Ends); strcat(info, "\n "); if(myauc->EndsValue > 0) { time_t tt = myauc->EndsValue - timeDiff; struct tm *lt = localtime(&tt); memset(temp2, 0, sizeof temp2); strftime(temp2, sizeof temp2, "%m/%d/%y, %H:%M:%S", lt); strcat(info, temp2); } strcat(info, "\n "); stringTimeLeft(myauc, timeDiff, temp2); strcat(info, temp2); strcat(info, "\n "); // obviously there is at least 1 item if(myauc->Quantity < 1) myauc->Quantity = 1; quant = g_strdup_printf("%d", myauc->Quantity); strcat(info, quant); g_free(quant); strcat(info, "\n "); bidc = g_strdup_printf("%d", myauc->BidCount); strcat(info, bidc); g_free(bidc); strcat(info, "\n "); strcat(info, myauc->HighBidder); strcat(info, myauc->BidderRate); strcat(info, "\n "); strcat(info, myauc->currency); strcat(info, temp); strcat(info, "\n "); strcat(info, myauc->currency); sprintf(temp, "%.2f", myauc->FirstBid); strcat(info, temp); strcat(info, "\n "); strcat(info, myauc->currency); char cbid1[10]; sprintf(cbid1, "%.2f", myauc->BuyitNowPrice); strcat(info, cbid1); strcat(info, "\n "); for(int i = 0; i < 3; i++) { if(myauc->Shipping[i] > 0) { char buf[100]; sprintf(buf, "%s%.2f\n ", myauc->ShippingCur[i], myauc->Shipping[i]); strcat(info, buf); } else { strcat(info, "\n "); } } // deal with snipes and quantity - // DBS if (myauc->isSnipe && strcmp(myauc->HighBidder, "Dutch Auction") == 0) { char ts[100]; sprintf(ts, "%d%s%s%.2f each", myauc->snipeQty, unitstring, myauc->currency, myauc->snipeAmount); strcat(info, ts); } else { if (myauc->isSnipe) { char ts[100]; sprintf(ts, "%s%.2f", myauc->currency, myauc->snipeAmount); strcat(info, ts); } } removeAscii127(info); gtk_label_set_text(GTK_LABEL(infolabel), info); /* gtk_widget_set_sensitive(sellerbutton, FALSE); gtk_widget_set_sensitive(bidderbutton, FALSE); */ } DetailsWindow::~DetailsWindow() { if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); gtk_timeout_remove(timeouttag); } CommentWindow::CommentWindow(struct auctioninfo *auc) { myauc = auc; window = gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window), 10); gtk_window_set_default_size(GTK_WINDOW(window), 300, 103); char *title = g_strdup_printf("Comments for Item #"LLU_FMT, auc->ItemNumber); gtk_window_set_title(GTK_WINDOW(window), title); g_free(title); scrolledwindow = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow); gtk_box_pack_start(GTK_BOX(GTK_BOX(GTK_DIALOG(window)->vbox)), scrolledwindow, TRUE, TRUE, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); text = gtk_text_new(NULL, NULL); gtk_text_set_editable(GTK_TEXT(text), TRUE); if (myauc->Comments[0] != '\0') gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, myauc->Comments, strlen(myauc->Comments)); gtk_widget_show(text); gtk_container_add(GTK_CONTAINER(scrolledwindow), text); okbutton = gtk_button_new_with_label("OK"); cancelbutton = gtk_button_new_with_label("Cancel"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), cancelbutton, FALSE, FALSE, 0); gtk_signal_connect (GTK_OBJECT(cancelbutton), "clicked", GTK_SIGNAL_FUNC(commentclose_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC (commentdestroy_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT(okbutton), "clicked", GTK_SIGNAL_FUNC (commentok_callback), (gpointer) this); gtk_widget_show(okbutton); gtk_widget_show(cancelbutton); gtk_widget_show(window); commentOpen = TRUE; } BidWindow::BidWindow(struct auctioninfo *auc) { // if ((authID[0] == '\0') || (authPASS[0] == '\0')) { /* No UserID or pass. don't allow this. */ // showError("Missing Username or Password."); // return; // } updateitem_handler(NULL, NULL); myauc = auc; window = gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window), 10); char currentbid[80], chTemp[80]; char *title = g_strdup_printf("Item Number : "LLU_FMT, myauc->ItemNumber); gtk_window_set_title(GTK_WINDOW(window), title); g_free(title); sprintf(currentbid, "Current Bid : %s%.2f", myauc->currency, myauc->CurrentBid); if (myauc->reserveMet == 'y') strcat(currentbid, " - reserve met"); else if (myauc->reserveMet == 'n') strcat(currentbid, " - reserve not met"); else if (myauc->reserveMet == 'x') strcat(currentbid, " - no reserve"); else if (myauc->reserveMet == 'b') strcat(currentbid, " - BuyItNow Only"); currentbidlabel = gtk_label_new(currentbid); stringTimeLeft(myauc, timeDiff, chTemp); sprintf(currentbid, "Time Left : %s", chTemp); timeleftlabel = gtk_label_new(currentbid); gtk_widget_show(currentbidlabel); gtk_widget_show(timeleftlabel); sprintf(chTemp, "%.2f", myauc->minBid()); bidlabel = gtk_label_new("Your MAXIMUM bid"); bidtext = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(bidtext), chTemp); gtk_signal_connect(GTK_OBJECT(bidtext), "activate", GTK_SIGNAL_FUNC(bidnow_callback), (gpointer) this); bidbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(bidbox), bidtext, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(bidbox), bidlabel, FALSE, FALSE, 0); gtk_widget_show(bidlabel); gtk_widget_show(bidtext); gtk_widget_show(bidbox); quantitylabel = gtk_label_new("Dutch Auction Quantity"); quantitytext = gtk_entry_new(); quantitybox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(quantitybox), quantitytext, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(quantitybox), quantitylabel, FALSE, FALSE, 0); gtk_entry_set_text(GTK_ENTRY(quantitytext), "1"); gtk_widget_set_sensitive(quantitylabel, !strcmp(myauc->HighBidder, "Dutch Auction")); gtk_widget_set_sensitive(quantitytext, !strcmp(myauc->HighBidder, "Dutch Auction")); gtk_widget_show(quantitylabel); gtk_widget_show(quantitytext); gtk_widget_show(quantitybox); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), timeleftlabel, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), currentbidlabel, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->vbox), bidbox, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->vbox), quantitybox, FALSE, FALSE, 0); radio_snipe = gtk_radio_button_new_with_label(NULL, "Snipe"); radio_bid = gtk_radio_button_new_with_label(gtk_radio_button_group(GTK_RADIO_BUTTON(radio_snipe)), "Bid"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), radio_bid, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), radio_snipe, FALSE, FALSE, 0); gtk_widget_show(radio_bid); gtk_widget_show(radio_snipe); okbutton = gtk_button_new_with_label("OK"); cancelbutton = gtk_button_new_with_label("Cancel"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), cancelbutton, FALSE, FALSE, 0); /* This doesn't make sense, since some buyitnows can be bid on, while * others can't. We must distinguish. // if (auc->reserveMet == 'b') if (auc->isBuyitNow == TRUE) // Disallow bidding on buyitnow only listings gtk_widget_set_sensitive(okbutton, FALSE); */ gtk_widget_show(okbutton); gtk_widget_show(cancelbutton); gtk_widget_show(window); gtk_signal_connect (GTK_OBJECT(cancelbutton), "clicked", GTK_SIGNAL_FUNC(bidclose_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC (biddestroy_callback), (gpointer) this); gtk_signal_connect (GTK_OBJECT(okbutton), "clicked", GTK_SIGNAL_FUNC (bidnow_callback), (gpointer) this); } EndedWindow::EndedWindow(char snipes, char current) { issnipes = snipes; iscurrent = current; window = gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window), 10); gtk_widget_set_usize(window, 500, 300); hbox = gtk_hbox_new(FALSE, 0); textbuffer = gtk_text_new(NULL, NULL); scrollbar = gtk_vscrollbar_new(GTK_TEXT(textbuffer)->vadj); gtk_text_set_editable(GTK_TEXT(textbuffer), FALSE); gtk_box_pack_start(GTK_BOX(hbox), textbuffer, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(hbox), scrollbar, FALSE, FALSE, 0); gtk_widget_show(textbuffer); gtk_widget_show(scrollbar); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), hbox, TRUE, TRUE, 0); monthbutton = gtk_button_new(); monthlabel = gtk_label_new(""); gtk_container_add(GTK_CONTAINER(monthbutton), monthlabel); okbutton = gtk_button_new_with_label("OK"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area), monthbutton, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), okbutton, FALSE, FALSE, 0); gtk_widget_show(monthbutton); gtk_widget_show(monthlabel); gtk_widget_show(okbutton); gtk_widget_show(window); gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", GTK_SIGNAL_FUNC (endedclose_callback), (gpointer) this); // gtk_signal_connect (GTK_OBJECT (window), "destroy", // GTK_SIGNAL_FUNC (endedclose_callback), // (gpointer) this); gtk_signal_connect (GTK_OBJECT (monthbutton), "clicked", GTK_SIGNAL_FUNC (endedmonth_callback), (gpointer) this); update(); } void EndedWindow::update() { if (gtk_text_get_length(GTK_TEXT(textbuffer)) > 0) { gtk_text_set_point(GTK_TEXT(textbuffer), 0); gtk_text_forward_delete(GTK_TEXT(textbuffer), gtk_text_get_length(GTK_TEXT(textbuffer))); } char fileName[200]; char *fnstring; if (issnipes) { fnstring = g_strdup_printf("/%s/snipe", bw_subdir); MakeFileName(fnstring, fileName, iscurrent); gtk_window_set_title(GTK_WINDOW(window), iscurrent ? "This month's snipes" : "Last month's snipes"); g_free(fnstring); } else { fnstring = g_strdup_printf("/%s/log", bw_subdir); MakeFileName(fnstring, fileName, iscurrent); gtk_window_set_title(GTK_WINDOW(window), iscurrent ? "This month's ended auctions" : "Last month's ended auctions"); g_free(fnstring); } gtk_label_set_text(GTK_LABEL(monthlabel), iscurrent ? "View last month" : "View this month"); FILE *infile = fopen(fileName, "r"); if (infile) { char buffer[1024]; int nchars; while (1) { nchars = fread(buffer, 1, 1024, infile); gtk_text_insert (GTK_TEXT (textbuffer), fixed_font, NULL, NULL, buffer, nchars); if (nchars < 1024) break; } fclose (infile); } } EndedWindow::~EndedWindow() { if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); } static void details_handler(GtkMenuItem *menuitem,gpointer data) { // Ensure that we are in the zone. if (!isValidAuction(currentauc)) return; new DetailsWindow(auction[currentauc]); } gint selection_clear(GtkWidget *widget, GdkEventSelection *event, gint *have_selection) { selection_id = 0; return TRUE; } void selection_handle(GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time_stamp, gpointer data) { /* This doesn't work yet. */ static gchar id[20]; //id = (char *) malloc(20); memset(id, 0, sizeof(id)); strcpy(id, "Testing."); /* g_print("Handling Selection: %s\n", id); g_print(" aSD->type == %s\n aSD->target == %s\n info == %s\n", gdk_atom_name(selection_data->type), gdk_atom_name(selection_data->target), gdk_atom_name(info)); */ /* When we return a single string, it should not be null terminated. That will be done for us */ // gtk_selection_data_set(selection_data, GDK_SELECTION_TYPE_STRING, // 8, (const guchar *) "HI", 2); // free(id); // long unsigned int blah; // XChangeProperty(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window), XA_STRING, blah, // 8, PropModeReplace, (unsigned char*) "Hi", 2); } void unbid_handler(GtkMenuItem *MenuItem, gpointer data) { if (!isValidAuction(currentauc)) return; int indx = currentauc; ClearSnipe(indx); } static void bid_handler(GtkMenuItem *menuitem, gpointer data) { if (!isValidAuction(currentauc)) return; new BidWindow(auction[currentauc]); } static void showauctions_handler(GtkMenuItem *menuitem, gpointer data) { new EndedWindow(FALSE, TRUE); } static void showsnipes_handler(GtkMenuItem *menuitem, gpointer data) { new EndedWindow(TRUE, TRUE); } static void loadauc_handler(GtkMenuItem *MenuItem, gpointer data) { if (!isValidAuction(currentauc)) return; int choice = currentauc; launchBrowser(choice); } static void comments_handler(GtkMenuItem *MenuItem, gpointer data) { if (!commentOpen) comwindow = new CommentWindow(auction[currentauc]); } static void config_callback(GtkWidget *widget, gpointer data) { if (!configOpen) confwindow=new ConfigWindow(); } static void add_callback(GtkWidget *widget, gpointer data) { if (updateInProgress == TRUE) { // Is this actually necessary? showError("Error: Can't add auction while updating auctions." ); } else { char *t = strstr(gtk_entry_get_text(GTK_ENTRY(data)), "item="); if (t) addNewItem(strtoull(t+5, (char **)NULL, 10)); else addNewItem(strtoull(gtk_entry_get_text(GTK_ENTRY(data)), (char **)NULL, 10)); gtk_entry_set_text(GTK_ENTRY(data), ""); } } static void add_activate(GtkWidget *widget, gpointer data) { // Callback to catch the user hitting enter on the // addentry box. phear the elite passthru to add_callback ;) add_callback(widget, data); } static void help_callback(GtkWidget *widget, gpointer data) { if (!helpOpen) new AboutWindow(); } static GtkItemFactoryEntry popupmenu_items[]={ { "/Show item details",NULL,(GtkItemFactoryCallback)details_handler,0,NULL }, //{ "/Copy item number", NULL, (GtkItemFactoryCallback)copy_item_number, 0, // NULL }, { "/Open browser to this auction",NULL, (GtkItemFactoryCallback)loadauc_handler, 0, NULL }, { "/Set Comments", NULL, (GtkItemFactoryCallback)comments_handler, 0, NULL }, { "/Update this auction", NULL, (GtkItemFactoryCallback)updateitem_handler, 0, NULL }, { "/Bid or set up snipe", NULL, (GtkItemFactoryCallback)bid_handler, 0, NULL }, { "/Cancel snipe", NULL, (GtkItemFactoryCallback)unbid_handler, 0, NULL }, { "/Delete this item", NULL, (GtkItemFactoryCallback)deleteitem_handler, 0, NULL }, { "/Delete ALL auctions", NULL, (GtkItemFactoryCallback)flush_handler, 0, NULL }, { "/View completed snipes", NULL,(GtkItemFactoryCallback)showsnipes_handler, 0, NULL }, { "/View completed auctions", NULL, (GtkItemFactoryCallback)showauctions_handler, 0, NULL } }; static gint popupnum_items=sizeof(popupmenu_items)/sizeof(popupmenu_items[0]); class PopupMenu { public: GtkItemFactory *factory; GtkWidget *menu; PopupMenu() { factory = gtk_item_factory_new(GTK_TYPE_MENU, "", NULL); gtk_item_factory_create_items(factory, popupnum_items, popupmenu_items, NULL); menu = gtk_item_factory_get_widget(factory, ""); } }; static gint select_row_handler(GtkWidget *widget,gint row, gint col, GdkEventButton *event, gpointer data) { if (event == NULL) return FALSE; currentauc = row; return FALSE; // not handled } static gint button_press_event_handler(GtkWidget *w, GdkEventButton *event, gpointer d) { gint row, col; if (w == NULL || event == NULL) { showError("Please select an auction first"); return FALSE; } gtk_clist_get_selection_info(GTK_CLIST(w), (gint) event->x, (gint) event->y, &row, &col); if(event->button == 2 || (event->button == 1 && (event->state & GDK_CONTROL_MASK))) switchBidGroup(auction, aucIdx, currentauc, row, bw_subdir, timeDiff, authID); // always call before setting currentauc currentauc = row; if (aucIdx != 0) { if (event->type == GDK_2BUTTON_PRESS) { loadauc_handler(NULL, NULL); return TRUE; } if (event->button == 3) {// right mouse button gtk_menu_popup(GTK_MENU(popupmenu->menu), NULL, NULL, NULL, NULL, event->button, 1); gtk_signal_emit_stop_by_name(GTK_OBJECT(w), "button_press_event"); return TRUE; } } return FALSE; } void drophandler(GtkWidget *w, GdkDragContext *c, gint x, gint y, GtkSelectionData *data, guint inf, guint time, gpointer info) { char *item=strstr((char *)data->data,"item="); if (item==NULL) gtk_drag_finish (c,FALSE,FALSE,time); else { item+=strlen("item="); char itemnumbuf[20]; strnzcpy(itemnumbuf,item,strspn(item,"0123456789")); addNewItem(atoull(itemnumbuf)); gtk_drag_finish (c,TRUE,FALSE,time); } } // Make a GtkPixmap out of the given xpm data; uses style of toplevel // for transparent color of xpm GtkWidget* makeicon(GtkWidget* toplevel, char** xpm) { GdkBitmap* mask; GtkStyle* style = gtk_widget_get_style(toplevel); GdkPixmap* pixmap = gdk_pixmap_create_from_xpm_d(toplevel->window, &mask, &style->bg[GTK_STATE_NORMAL], xpm); GtkWidget* pixmapwid = gtk_pixmap_new(pixmap, mask); return pixmapwid; } int updateInterval(int timeLeft) { if (timeLeft < 3 * 60) return update_prio1_interval; if (timeLeft < 15 * 60) return update_prio2_interval; if (timeLeft < 2 * 60 * 60) return update_prio3_interval; return update_prio4_interval; } static int timer_tick = 10; void timeout1Up(gpointer data = 0) { int next_end = timeToNextEnd(); timer_tick = updateInterval(next_end); next_end += 2; if(next_end > 0 && timer_tick > next_end) timer_tick = next_end; const int max_update = 60; if(timer_tick > max_update && haveEndedWithoutUpdate()) timer_tick = max_update; const int min_update = 1; if(timer_tick < min_update) timer_tick = min_update; static guint timer_id = 0; if(timer_id) g_source_remove(timer_id); timer_id = g_timeout_add_full(100, timer_tick * 1000, updatelist_callback, NULL, NULL); } void init() { GdkPixmap *window_icon_PM; GdkBitmap *mask; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL); gtk_signal_connect(GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (destroy_event), NULL); // Let's us track movements of the window gtk_signal_connect(GTK_OBJECT (window), "configure_event", GTK_SIGNAL_FUNC (configure_event), NULL); clockIsSet = FALSE; updateInProgress = FALSE; trackBids = trackListings = autoDelete = doStartup = TRUE; numbids = aucIdx = Timer1Idx = timeDiff = 0; security = SEC_LOW; snipeDelay = 15; update_prio1_interval = 10; update_prio2_interval = 60; update_prio3_interval = 300; update_prio4_interval = 900; country = 0; // USA is the default gtk_window_set_default_size(GTK_WINDOW(window), 870, 230); tooltips = gtk_tooltips_new(); memset(authID, 0, sizeof(authID)); memset(authPASS, 0, sizeof(authPASS)); memset(proxystring, 0, sizeof(proxystring)); strcpy(browserPATH, "netscape"); strcpy(emailPATH, "xterm -e pine"); popupmenu = new PopupMenu(); char fileName[200]; char *homeDir = getenv("HOME"); strcpy(fileName, homeDir); strcat(fileName, "/"); strcat(fileName, bw_subdir); mkdir(fileName, 0700); ReadAucFile(); umask(0077); // make sure files are private GtkStyle *style=gtk_widget_get_style(window); GtkWidget *vbox=gtk_vbox_new(FALSE,0); GdkPixmap *userPM, *plusPM, *clockPM, *updatePM, *helpPM, *exitPM, *stopPM, *usermask, *plusmask, *clockmask, *updatemask, *helpmask, *exitmask, *stopmask; if (retain_size) gtk_window_set_default_size(GTK_WINDOW(window), window_width, window_height); if (retain_location) // I have no idea why those are necessary, maybe it's just WM? gtk_widget_set_uposition(window, window_x-1, window_y-23); gtk_widget_show(window); /* Set the window manager icon */ window_icon_PM = gdk_pixmap_create_from_xpm_d(window->window, &mask, &style->bg[GTK_STATE_NORMAL], bidwatch_xpm); gdk_window_set_icon(window->window, NULL, window_icon_PM, mask); gdk_window_set_group(window->window, window->window); userPM=gdk_pixmap_create_from_xpm_d(window->window,&usermask, &style->bg[GTK_STATE_NORMAL], user_xpm); userPMW=gtk_pixmap_new(userPM,usermask); plusPM=gdk_pixmap_create_from_xpm_d(window->window,&plusmask, &style->bg[GTK_STATE_NORMAL], plus_xpm); plusPMW=gtk_pixmap_new(plusPM,plusmask); clockPM=gdk_pixmap_create_from_xpm_d(window->window,&clockmask, &style->bg[GTK_STATE_NORMAL], clock_xpm); clockPMW=gtk_pixmap_new(clockPM,clockmask); updatePM=gdk_pixmap_create_from_xpm_d(window->window,&updatemask, &style->bg[GTK_STATE_NORMAL], update_xpm); updatePMW=gtk_pixmap_new(updatePM,updatemask); helpPM=gdk_pixmap_create_from_xpm_d(window->window,&helpmask, &style->bg[GTK_STATE_NORMAL], help_xpm); helpPMW=gtk_pixmap_new(helpPM,helpmask); exitPM=gdk_pixmap_create_from_xpm_d(window->window,&exitmask, &style->bg[GTK_STATE_NORMAL], exit_xpm); exitPMW=gtk_pixmap_new(exitPM,exitmask); stopPM=gdk_pixmap_create_from_xpm_d(window->window,&stopmask, &style->bg[GTK_STATE_NORMAL], stop_xpm); stopPMW=gtk_pixmap_new(stopPM,stopmask); redledPM=gdk_pixmap_create_from_xpm_d(window->window,&redledmask, &style->bg[GTK_STATE_NORMAL], redled_xpm); blueledPM=gdk_pixmap_create_from_xpm_d(window->window,&blueledmask, &style->bg[GTK_STATE_NORMAL], blueled_xpm); greenledPM=gdk_pixmap_create_from_xpm_d(window->window,&greenledmask, &style->bg[GTK_STATE_NORMAL], greenled_xpm); blackledPM=gdk_pixmap_create_from_xpm_d(window->window,&blackledmask, &style->bg[GTK_STATE_NORMAL], blackled_xpm); blackled=gtk_pixmap_new(blackledPM,blackledmask); arrowPM=gdk_pixmap_create_from_xpm_d(window->window,&arrowmask, &style->bg[GTK_STATE_NORMAL], arrow_xpm); userBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (userBut),userPMW); plusBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (plusBut),plusPMW); clockBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (clockBut),clockPMW); updateBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (updateBut),updatePMW); helpBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (helpBut),helpPMW); exitBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (exitBut),exitPMW); stopBut=gtk_button_new(); gtk_container_add(GTK_CONTAINER (stopBut),stopPMW); statusbox=gtk_hbox_new(FALSE,0); statuslabel=gtk_label_new(""); showStatus(""); gtk_label_set_justify(GTK_LABEL(statuslabel),GTK_JUSTIFY_LEFT); gtk_widget_set_usize(statuslabel,150,8); servertimelabel=gtk_label_new(""); gtk_label_set_justify(GTK_LABEL(servertimelabel),GTK_JUSTIFY_RIGHT); ebtime = gtk_event_box_new(); localtimelabel=gtk_label_new(""); gtk_label_set_justify(GTK_LABEL(localtimelabel),GTK_JUSTIFY_RIGHT); gtk_box_pack_start(GTK_BOX(statusbox), statuslabel, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(statusbox), servertimelabel, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(statusbox), ebtime, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(ebtime), localtimelabel); gtk_widget_set_events (ebtime, GDK_BUTTON_PRESS_MASK); gtk_signal_connect (GTK_OBJECT (ebtime), "button_press_event", GTK_SIGNAL_FUNC (toggle_localtime), NULL); // gtk_box_pack_start(GTK_BOX(statusbox), localtimelabel, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(statusbox), blackled, FALSE, FALSE, 0); gtk_widget_show(ebtime); gtk_widget_show(blackled); gtk_widget_show(localtimelabel); gtk_widget_show(statusbox); errorbox=gtk_vbox_new(FALSE,0); errorstat=gtk_statusbar_new(); errorcontext=gtk_statusbar_get_context_id(GTK_STATUSBAR(errorstat), "error status bar"); gtk_box_pack_start(GTK_BOX(errorbox),errorstat, FALSE, FALSE, 0); showBidStatus(banner1); showBidStatus(banner2); gtk_widget_show(errorstat); gtk_widget_show(errorbox); GtkWidget *buttonbox=gtk_hbox_new(FALSE,0); gtk_button_set_relief(GTK_BUTTON(userBut),GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(plusBut),GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(clockBut),GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(updateBut),GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(helpBut),GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(exitBut),GTK_RELIEF_NONE); gtk_button_set_relief(GTK_BUTTON(stopBut),GTK_RELIEF_NONE); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),userBut,"preferences",NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),plusBut, "add auction by number",NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),clockBut,"sync clock",NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),updateBut, "pull info from eBay NOW",NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),helpBut, "about bidwatcher",NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),exitBut,"quit",NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),stopBut,"stop",NULL); addentry = gtk_entry_new(); gtk_signal_connect(GTK_OBJECT (userBut), "clicked", GTK_SIGNAL_FUNC (config_callback), NULL); gtk_signal_connect(GTK_OBJECT (plusBut), "clicked", GTK_SIGNAL_FUNC (add_callback), addentry); gtk_signal_connect(GTK_OBJECT (helpBut), "clicked", GTK_SIGNAL_FUNC (help_callback), NULL); gtk_signal_connect(GTK_OBJECT (clockBut), "clicked", GTK_SIGNAL_FUNC (timesync_callback), NULL); gtk_signal_connect(GTK_OBJECT (exitBut), "clicked", GTK_SIGNAL_FUNC (exit_callback), NULL); gtk_signal_connect(GTK_OBJECT (updateBut), "clicked", GTK_SIGNAL_FUNC (update_callback), NULL); gtk_signal_connect(GTK_OBJECT (stopBut), "clicked", GTK_SIGNAL_FUNC (cancel_callback), NULL); // Catch user hitting enter gtk_signal_connect(GTK_OBJECT(addentry), "activate", GTK_SIGNAL_FUNC(add_activate), addentry); // Copy/Paste gtk_signal_connect(GTK_OBJECT (addentry), "selection_clear_event", GTK_SIGNAL_FUNC (selection_clear), NULL); gtk_selection_add_target(addentry, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 1); gtk_signal_connect(GTK_OBJECT (addentry), "selection_get", GTK_SIGNAL_FUNC (selection_handle), NULL); gtk_box_pack_start(GTK_BOX(buttonbox), userBut, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), clockBut, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), updateBut, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), helpBut, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), exitBut, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), plusBut, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), addentry, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), stopBut, FALSE, FALSE, 0); statuswindow = gtk_event_box_new(); GtkWidget *outerwindow = gtk_event_box_new(); gtk_widget_show(statuswindow); gtk_widget_show(outerwindow); gtk_container_add(GTK_CONTAINER(statuswindow), statusbox); gtk_container_add(GTK_CONTAINER(outerwindow), statuswindow); gtk_container_set_border_width(GTK_CONTAINER(outerwindow), 5); gtk_box_pack_start(GTK_BOX(buttonbox), outerwindow, FALSE, FALSE, 0); gtk_widget_set_style(statuswindow, greenstyle); gtk_widget_set_style(statuslabel, greenstyle); gtk_widget_set_style(servertimelabel, greenstyle); gtk_widget_set_style(ebtime, greenstyle); gtk_widget_set_style(localtimelabel, greenstyle); gtk_box_pack_start(GTK_BOX(vbox), buttonbox, FALSE, FALSE, 0); // Build the clist 0 1 2 3 4 5 6 7 gchar *titles[]={"Number","Current Bid","Time left","Bid","Description","Seller","FeedBack","Comments"}; /* Scrolled window for the clist */ GtkWidget *scrolled_window=gtk_scrolled_window_new(NULL,NULL); /* Make the bars automatic, no need to have em if we don't need em */ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); aucList = gtk_clist_new_with_titles(NUM_COLUMNS, titles); gtk_clist_column_titles_passive(GTK_CLIST(aucList)); gtk_clist_set_column_width(GTK_CLIST(aucList), 0, 100); gtk_clist_set_column_width(GTK_CLIST(aucList), 1, 160); gtk_clist_set_column_width(GTK_CLIST(aucList), 2, 110); gtk_clist_set_column_width(GTK_CLIST(aucList), 3, 70); gtk_clist_set_column_width(GTK_CLIST(aucList), 4, 350); gtk_clist_set_column_width(GTK_CLIST(aucList), 5, 120); gtk_clist_set_column_width(GTK_CLIST(aucList), 6, 80); gtk_clist_set_column_width(GTK_CLIST(aucList), 7, 300); gtk_clist_set_selection_mode(GTK_CLIST(aucList), GTK_SELECTION_SINGLE); gtk_clist_set_shadow_type(GTK_CLIST(aucList), GTK_SHADOW_NONE); gtk_signal_connect(GTK_OBJECT(aucList), "select_row", GTK_SIGNAL_FUNC(select_row_handler), NULL); gtk_signal_connect(GTK_OBJECT(aucList), "unselect_row", GTK_SIGNAL_FUNC(select_row_handler), NULL); gtk_signal_connect(GTK_OBJECT(aucList), "button_press_event", GTK_SIGNAL_FUNC(button_press_event_handler), NULL); gtk_drag_dest_set(aucList, GTK_DEST_DEFAULT_ALL, target_table, n_targets, GDK_ACTION_DEFAULT); gtk_signal_connect(GTK_OBJECT(aucList), "drag_data_received", GTK_SIGNAL_FUNC(drophandler), NULL); gtk_container_add(GTK_CONTAINER(scrolled_window), aucList); gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0); /* End of clist */ gtk_box_pack_start(GTK_BOX(vbox), errorbox, FALSE, FALSE, 0); gtk_widget_set_style(aucList, clean14style); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show_all(window); if (strlen(authID) > 1) { char capt[150]; strcpy(capt, "bidwatcher - "); strcat(capt, authID); gtk_window_set_title(GTK_WINDOW(window), capt); } else gtk_window_set_title(GTK_WINDOW(window), "bidwatcher"); // getAdultCookie(authID, authPASS); timer1Up(); g_timeout_add(1000, secondticker_callback, NULL); g_timeout_add(BIGDELAY, bigdelay_callback, NULL); timeout1Up(); // until we know better, don't waste bandwidth } // end constructor ///////////////////////////////////////////////////////////////////////////// // WriteAucFile // writes the configuration file ///////////////////////////////////////////////////////////////////////////// void WriteAucFile() { char fileName[200]; sprintf(fileName, "%s/%s/bw2.cfg", getenv("HOME"), bw_subdir); FopenW file(fileName); if (file == NULL) { fprintf(stderr, "Error opening configuration file %s!\n", fileName); return; } fprintf(file, "option tracklistings %s\n", trackListings?"yes":"no"); fprintf(file, "option trackbids %s\n", trackBids?"yes":"no"); fprintf(file, "option updateonstartup %s\n", doStartup?"yes":"no"); fprintf(file, "option autodelete %s\n", autoDelete?"yes":"no"); fprintf(file, "option snipedelay %i\n", snipeDelay); fprintf(file, "option update_prio1_int %i\n", update_prio1_interval); fprintf(file, "option update_prio2_int %i\n", update_prio2_interval); fprintf(file, "option update_prio3_int %i\n", update_prio3_interval); fprintf(file, "option update_prio4_int %i\n", update_prio4_interval); fprintf(file, "option security %i\n", security); fprintf(file, "option country %i\n", country); if (clockIsSet) fprintf(file,"option timediff %d\n",timeDiff); if (retain_location) fprintf(file, "option windowlocation %d %d\n", window_x, window_y); if (retain_size) fprintf(file, "option windowsize %d %d\n", window_width, window_height); if (security != SEC_HIGH) { if (authID[0]!='\0') fprintf(file, "user %s ", authID); if ((authPASS[0]!='\0') && (security != SEC_MED)) fprintf(file, "%s\n", authPASS); else fprintf(file, "nopass\n"); } if (browserPATH[0] != '\0') fprintf(file, "option browser %s\n", browserPATH); if (emailPATH[0] != '\0') fprintf(file, "option emailclient %s\n", emailPATH); if (proxystring[0] != '\0') fprintf(file, "option proxy %s\n", proxystring); if (proxyuserstring[0] != '\0') fprintf(file, "option proxyuser %s\n", proxyuserstring); if (proxypassstring[0] != '\0') fprintf(file, "option proxypass %s\n", proxypassstring); if (fixedFont[0] != '\0') fprintf(file, "option fixedfont %s\n", fixedFont); if (cleanFont[0] != '\0') fprintf(file, "option cleanfont %s\n", cleanFont); /* Save our color configuration from the array */ for (int i=0; ired, colors[i]->green, colors[i]->blue); } for (int i=0; i < aucIdx; i++) { fprintf(file, "auction "LLU_FMT"\n", auction[i]->ItemNumber); fprintf(file, " desc %s\n", auction[i]->Description); if (auction[i]->Comments[0] != '\0') fprintf(file, " comm %s\n", auction[i]->Comments); fprintf(file, " ends %ld\n", auction[i]->EndsValue); fprintf(file, " mybid %.2f %d\n", auction[i]->myBidAmount, auction[i]->myBidQuantity); fprintf(file, " endless %i\n", auction[i]->isEndless); #ifdef DEBUGCONFIG DPRINTF(DMED, (" writing: mybid %.2f %d\n",auction[i]->myBidAmount, auction[i]->myBidQuantity)); #endif if (auction[i]->isSnipe) fprintf(file, " snipe %.2f %d\n",auction[i]->snipeAmount, auction[i]->snipeQty); fprintf(file, " endauction\n"); } writeBidGroup(bw_subdir); } BidWindow::~BidWindow() { if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); WriteAucFile(); } CommentWindow::~CommentWindow() { if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); commentOpen = FALSE; WriteAucFile(); } ///////////////////////////////////////////////////////////////////////////////// // CmWeb // Launches a web browser session for the selected myauc-> ///////////////////////////////////////////////////////////////////////////////// void launchBrowser(int choice) { /* This list is sync'd with the GUI list. */ char *countries[] = { "ebay.com", "ebay.de", "ebay.co.uk", "ebay.ca", "ebay.com.au", "ebay.it", "ebay.fr", "ebay.nl", "ebay.be", "ebay.ch", "ebay.at", "es.ebay.com", "ebay.co.nz", "ebay.com.sg", }; char url[200]; sprintf(url, VIEWURL, countries[country], auction[choice]->ItemNumber); DPRINTF(9, ("URL is %s; country is %s\n", url, countries[country])); char commandLine[500]; if (strlen(browserPATH) < 2) { showError("No Web Browser configured!"); return; } //check if netscape is running: char homePath[200]; char lockBuffer[200]; strcpy(homePath,getenv("HOME")); strcat(homePath, "/.netscape/lock"); int err = readlink(homePath, lockBuffer, 199); bool hit = TRUE; if (err < 0) hit = FALSE; if ((choice < 0) || (choice > aucIdx)) return; else if ((strstr(browserPATH, "scape") != NULL) && hit) { sprintf(commandLine, "exec %s -remote \"openURL(%s,new-window)\"", browserPATH, url); system(commandLine); } else if (strstr(browserPATH, "mozilla") != NULL) { // Try to find mozilla. sprintf(commandLine, "exec %s -remote \"openURL(%s,new-window)\"", browserPATH, url); // Mozilla returns 0 if it's running. int mozret = system(commandLine); if (mozret) { memset(commandLine, 0, sizeof commandLine); sprintf(commandLine, "exec %s \"%s\" &", browserPATH, url); system(commandLine); } } else { sprintf(commandLine, "exec %s \"%s\" &", browserPATH, url); system(commandLine); } } /* ////////////////////////////////////////////////////////////////////////////// // CmEmail // send email to person specified in char * recip ////////////////////////////////////////////////////////////////////////////// void CmEmail(char *recip) { int err; char commandLine[500]; char command[500]; if (strstr(emailPATH,"%s") == NULL) strcat(emailPATH, " %s"); err = sprintf(command, emailPATH, recip); strcpy(commandLine, "exec "); strcat(commandLine, command); strcat(commandLine, " "); strcat(commandLine, " &"); system(commandLine); } */ ////////////////////////////////////////////////////////////////////////////// // CmBid ////////////////////////////////////////////////////////////////////////////// void CmBid() { struct auctioninfo *newAuction; int choice = currentauc; newAuction = auction[choice]; if (strlen(newAuction->TimeLeft) < 3) { showStatus(" updating auction..."); int returnVal = newAuction->getinfo(); if (returnVal != INFO_SUCCESS) { showError("Can't update auction, network problems."); showStatus(""); return; } UpdateListItem(choice); } showStatus(""); new BidWindow(newAuction); } ////////////////////////////////////////////////////////////////////////// // ClearSnipe ////////////////////////////////////////////////////////////////////////// void ClearSnipe(int choice) { auction[choice]->isSnipe = FALSE; auction[choice]->isPreBid = FALSE; strcpy(auction[choice]->snipeKey, ""); auction[choice]->snipeAmount=0; auction[choice]->snipeQty=0; auction[choice]->myBidAmount=0; auction[choice]->myBidQuantity=0; UpdateListItem(choice); WriteAucFile(); } ///////////////////////////////////////////////////////////////////////////// // UpdateItem // responds to update this auction popup menu selection ///////////////////////////////////////////////////////////////////////////// static void updateitem_handler(GtkMenuItem *MenuItem, gpointer data) { if (!isValidAuction(currentauc)) return; int clickIndex = currentauc; if (updateInProgress == TRUE) return; updateInProgress = TRUE; struct auctioninfo *NewAuction; showStatus(" updating auction..."); NewAuction = auction[clickIndex]; int returnVal = NewAuction->getinfo(); switch(returnVal) { case INFO_SUCCESS: UpdateListItem(clickIndex); break; case INFO_BADAUCTION: showError("Invalid auction number. (uih)"); break; case INFO_TIMEOUT: showError("Timeout."); break; case INFO_CGIDOWN: showError("CGI server down."); break; case INFO_NETERROR: showError("Can't connect to server."); break; case INFO_USERCANCEL: /* ? */ break; default: /* ? */ break; } showStatus(""); updateInProgress = FALSE; } static void deleteitem_handler(GtkMenuItem *MenuItem, gpointer data) { if (!isValidAuction(currentauc)) return; if (updateInProgress == TRUE) return; updateInProgress = TRUE; int choice = currentauc; if (choice < 0) { updateInProgress = FALSE; return; // no item selected } DeleteAuction(choice); gtk_clist_remove(GTK_CLIST(aucList), choice); updateInProgress = FALSE; if (choice == (aucIdx)) gtk_clist_moveto(GTK_CLIST(aucList), choice - 1, 0, 0.5, 0.5); else gtk_clist_moveto(GTK_CLIST(aucList), choice - 1, 0, 0.5, 0.5); WriteAucFile(); UpdateList(); } static void flush_handler(GtkMenuItem *MenuItem,gpointer data) { new ConfirmWindow("Are you sure you want to delete all auctions?"); } ////////////////////////////////////////////////////////////////////////////// // flush: // all bets off, clears all the structs and emptys the .audFile // calls: // DeleteAuction(), UpdateList() ////////////////////////////////////////////////////////////////////////////// void flush() { int totalAucs = aucIdx; int i; if (updateInProgress == TRUE) return; if (totalAucs <= 0) return; updateInProgress = TRUE; for (i = 0; i < totalAucs; i++) ClearBidMakeUp(auction[i]); aucIdx = 0; numbids = 0; gtk_window_set_title(GTK_WINDOW(window),"bidwatcher"); UpdateList(); updateInProgress = FALSE; WriteAucFile(); } ////////////////////////////////////////////////////////////////////////////// // timeToNextEnd // Calculate the time until the next auction ends, in seconds ////////////////////////////////////////////////////////////////////////////// int timeToNextEnd(bool snipe_only, int *idx) { if(idx) *idx = -1; int intTimeLeft; int minTimeLeft = 9999999; for (int i = 0; i < aucIdx; i++) { if(snipe_only && !auction[i]->isSnipe) continue; intTimeLeft = CalcTimeLeft(auction[i]->EndsValue, timeDiff); if (intTimeLeft > -30 && intTimeLeft < minTimeLeft) { minTimeLeft = intTimeLeft; if(idx) *idx = i; } } return minTimeLeft; } int timeToNextSnipe(int *idx) { int def_idx; if(!idx) idx = &def_idx; int t = timeToNextEnd(true, idx); if(*idx < 0) return t; t -= snipeDelay; if(auction[*idx]->isPreBid) t -= PREBID_DELAY; return t; } bool interfereWithSnipe() { return timeToNextSnipe() < 2; } bool haveEndedWithoutUpdate() { for (int i = 0; i < aucIdx; i++) { int timeLeft = CalcTimeLeft(auction[i]->EndsValue, timeDiff); if(timeLeft < 0 && !auction[i]->finalUpdated()) return 1; } return 0; } /* Consolidated update function. To get UpdateAll behavior, * set minutes to -1. Otherwise, works like UpdateLatest */ int Update(int minutes, bool firstRun, bool fullUpdate) { if(firstRun) fullUpdate = TRUE; if (!firstRun && interfereWithSnipe()) { UpdateList(); return TRUE; } int prev_selected = currentauc; char numerator[4]; char denominator[4]; char message[20]; WriteAucFile(); showBidStatus("Refreshing auction information"); cancelPressed = FALSE; gtk_widget_show(stopBut); for (int idx=0; idx < aucIdx; idx++) { // Don't stop on snipes if (!firstRun && interfereWithSnipe()) { cancelPressed = FALSE; gtk_widget_hide(stopBut); UpdateList(); return TRUE; } strcpy(message, " updating "); sprintf(denominator, "%d", aucIdx); sprintf(numerator, "%d", (idx + 1)); strcat(message, numerator); strcat(message, "/"); strcat(message, denominator); showStatus(message); // if user pressed the cancel button, end the // update right here. if (cancelPressed == TRUE) { showStatus(""); cancelPressed = FALSE; gtk_widget_hide(stopBut); return FALSE; } int timeLeft = CalcTimeLeft(auction[idx]->EndsValue, timeDiff); // if auto delete is on AND the auction is older than the predefined // limit for keeping auctions in the list AND it is not a "Purchase Only" // auction if (autoDelete && timeLeft < AUTODEL && !auction[idx]->isEndless) { // delete it DeleteAuction(idx); gtk_clist_remove(GTK_CLIST(aucList), idx); idx--; continue; } if (!fullUpdate && auction[idx]->finalUpdated()) { continue; } // update auction according to update intervals int last_upd = -CalcTimeLeft(auction[idx]->UpdTime, timeDiff); int upd_interval = updateInterval(timeLeft); if(!fullUpdate && last_upd < upd_interval - timer_tick / 2) { continue; } if (minutes < 0 || timeLeft < minutes * 60) { int returnVal = auction[idx]->getinfo(); if (returnVal == INFO_SUCCESS) { UpdateList(); } else { // showStatus(""); if (returnVal == INFO_BADAUCTION && timeLeft > 0) { // Drop it if it's invalid, but not if ebay is just ailing. DeleteAuction(idx); gtk_clist_remove(GTK_CLIST(aucList), idx); idx--; } } continue; } } UpdateList(); gtk_clist_moveto(GTK_CLIST(aucList), prev_selected, 0, 0.5, 0.5); showStatus(""); cancelPressed = FALSE; gtk_widget_hide(stopBut); return TRUE; } int updateitem(unsigned long long inumber) { int returnVal; int idx; char numerator[4]; char denominator[4]; char message[20]; WriteAucFile(); gtk_widget_show(stopBut); cancelPressed = FALSE; for (idx=0;idxItemNumber == inumber) { strcpy(message, " Updating "); sprintf(denominator, "%d", aucIdx); sprintf(numerator, "%d", (idx + 1)); strcat(message, numerator); strcat(message, "/"); strcat(message, denominator); showStatus(message); // if user pressed the cancel button, end the // update right here. if (cancelPressed == TRUE) { showStatus(""); cancelPressed = FALSE; gtk_widget_hide(stopBut); return FALSE; } returnVal = auction[idx]->getinfo(); if (returnVal == INFO_SUCCESS) { UpdateListItem(idx); } else { showStatus(""); cancelPressed = FALSE; gtk_widget_hide(stopBut); return FALSE; } } } showStatus(""); cancelPressed = FALSE; gtk_widget_hide(stopBut); return FALSE; } ////////////////////////////////////////////////////////////////////////////// // addNewItem: // called when user enters a number via numberEdit, does some error // checking on the supplied auction number, and if it looks valid, // is submitted to the auction site for verification. // calls: // UpdateAuction(), DeleteAuction(), UpdateList() ////////////////////////////////////////////////////////////////////////////// struct auctioninfo *addNewItem(unsigned long long newNumber) { updateInProgress = TRUE; int i; int returnVal; if (aucIdx >= MAXAUCS) { // over the limit on auctions already showError("You already have the maximum allowed auctions." ); updateInProgress = FALSE; return NULL; } // scan current list, make sure this isn't a dup for (i=0; i < aucIdx; i++) { if (newNumber==auction[i]->ItemNumber) { // if the user is adding an auction that is already in the list, either // they do not know it is in the list or they forgot it was in the list. // however, since it IS in the list already we can just tell them it was // added. since they did not realize it was in the list already, to them // it looks as if we did just add it. // ** NOTE ** the real motivation here is not to show the user an "error" // message. This loop checks for dups for the caller instead of each // caller having to do it themselves. If we did not do it this way the // caller would have to duplicate this loop if he did not want to take // the chance of the user seeing an "error" message. DPRINTF(DLOW, ("The auction "LLU_FMT" is already in the list.\n", auction[i]->ItemNumber)); showStatus(""); updateInProgress = FALSE; return auction[i]; } } // now we're reasonably sure that this is an ebay auction - add it to // AucNumList, and submit to UpdateAuction. If it is a mistype or // otherwise not valid, it will be caught there and deleted, we will // notify user. showStatus(" adding auction..."); auction[aucIdx]=new auctioninfo(); struct auctioninfo * NewAuction=auction[aucIdx]; NewAuction->ItemNumber=newNumber; returnVal = NewAuction->getinfo(); if (returnVal == INFO_SUCCESS) { NewAuction->EndsValue = CalcEndsValue(NewAuction->Ends); aucIdx++; showStatus(""); UpdateList(); updateInProgress = FALSE; timeout1Up(); WriteAucFile(); return NewAuction; } else if (returnVal == INFO_BADAUCTION) { char msg[100]; snprintf(msg, 100, "Invalid auction number. ("LLU_FMT")", newNumber); showError(msg); } else if (returnVal == INFO_TIMEOUT) showError("Connection time-out"); else showError("Can't connect to server."); updateInProgress = FALSE; showStatus(""); return NULL; } ////////////////////////////////////////////////////////////////////////////// // timer1Up: // // calls: // UpdateAuction() ////////////////////////////////////////////////////////////////////////////// void timer1Up() { // this timer runs once on startup. updateInProgress = TRUE; UpdateList(); TimeSync(); if (doStartup) { if (strlen(authID)>2 && GetUserBids() == GUA_SUCCESS) { GetUserListings(); } Update(-1, TRUE, TRUE); } UpdateList(); updateInProgress = FALSE; } gint secondticker_callback(gpointer data) // second ticker { addItemsFromFile(bw_subdir, updateInProgress); static volatile int checking_snipes = FALSE; if (clockIsSet) { int timeLeft; char newTime[10]; int alarm_level = 0; #ifdef DEBUG_NETWORK static int prev_snipe_delay = 0; #endif int cur_snipe_delay = snipeDelay; int snipe_adj = (int)((avg_load_time - NORMAL_LOAD_TIME + 500)/1000); if (snipe_adj > 0) { cur_snipe_delay += snipe_adj; #ifdef DEBUG_NETWORK if (prev_snipe_delay != cur_snipe_delay) { fprintf(stderr, "poor network response: " "Adjusting snipe delay from %d to %d\n", snipeDelay, cur_snipe_delay); prev_snipe_delay = cur_snipe_delay; } #endif } #ifdef DEBUG_NETWORK else { prev_snipe_delay = 0; } #endif for (int i=0; i < aucIdx; i++) { if (auction[i]->isSnipe) { timeLeft = CalcTimeLeft(auction[i]->EndsValue, timeDiff); if (!checking_snipes && timeLeft > -30) { checking_snipes = TRUE; if(timeLeft < cur_snipe_delay + PREBID_DELAY) { if(auction[i]->isPreBid) { auction[i]->isPreBid = FALSE; auction[i]->getkey(auction[i]->snipeAmount, auction[i]->snipeQty); } } if (timeLeft < cur_snipe_delay) { auction[i]->isSnipe = FALSE; if(auction[i]->snipeKey[0]) DoSnipe(i); } checking_snipes = FALSE; } if (timeLeft > -5) { if (timeLeft < 120) alarm_level = 2; else if (timeLeft < 1800) { if (alarm_level < 1) alarm_level = 1; } } } } if (alarm_level == 0) gtk_widget_set_style (servertimelabel, greenstyle); else if (alarm_level == 1) gtk_widget_set_style (servertimelabel, yellowstyle); else if (alarm_level == 2) gtk_widget_set_style (servertimelabel, redstyle); MakeClockTime(timeDiff, newTime); gtk_label_set_text(GTK_LABEL(servertimelabel),newTime); } else gtk_label_set_text(GTK_LABEL(servertimelabel),"no sync"); // We allow this field to be toggled via click // I had some great idea about what should be shown and then // I decided it was dumb, help me out ;) char *t; switch(localtimeval) { case 1: t = g_strdup_printf(" Next: "); gtk_label_set_text(GTK_LABEL(localtimelabel),t); g_free(t); break; case 2: // gtk_label_set_text(GTK_LABEL(localtimelabel,t); break; case 0: default: char newLocalTime[10]; MakeClockTime(0, newLocalTime); t = g_strdup_printf(" (local: %s)", newLocalTime); gtk_label_set_text(GTK_LABEL(localtimelabel),t); g_free(t); } return TRUE; } ////////////////////////////////////////////////////////////////////////////// // bigUpdate // triggers an UpdateAll every BIGDELAY mSeconds. if there is an // update in progress, tries again in 2 minutes ////////////////////////////////////////////////////////////////////////////// bool bigUpdate() { // Note: If we return TRUE at any point in this function, our bigdelay // gtk timer will be reset for us so that the bigUpdate will be tried // again in about 2 minutes. By returning FALSE, we are telling the // gtk timer to call us again in the original amount of time. if (updateInProgress) return TRUE; if (interfereWithSnipe()) return TRUE; TimeSync(); if (interfereWithSnipe()) return TRUE; updateInProgress=TRUE; if (GetUserBids() == GUA_SUCCESS) { // We check each time to see if enough time passed to put us within // the 5 minute period before a snipe. Snipes take priority over // cosmetic updates. if (interfereWithSnipe()) return TRUE; GetUserListings(); if (interfereWithSnipe()) return TRUE; UpdateList(); if (interfereWithSnipe()) return TRUE; if (Update(-1, FALSE, TRUE) == FALSE) return TRUE; } updateInProgress=FALSE; return FALSE; } ////////////////////////////////////////////////////////////////////////////// // timer3up: // triggers an UpdateAll every BIGDELAY mSeconds. if there is an // update in progress, tries again in 2 minutes ////////////////////////////////////////////////////////////////////////////// gint bigdelay_callback(gpointer data) { if (bigUpdate()) { // Try again later. g_timeout_add(2*60*1000, bigdelay_callback, NULL); DPRINTF(DHIGH, ("Next bigUpdate() in 2 minutes.\n")); } else { g_timeout_add(BIGDELAY, bigdelay_callback, NULL); DPRINTF(DHIGH, ("Next bigUpdate() in %i minutes.\n", BIGDELAY/60/1000)); } return FALSE; } ////////////////////////////////////////////////////////////////////////////// // timer4Up - schedules the next update of the list of auctions ////////////////////////////////////////////////////////////////////////////// gint updatelist_callback(gpointer data) { if (updateInProgress) return FALSE; updateInProgress = TRUE; Update(-1, FALSE, FALSE); updateInProgress = FALSE; timeout1Up(data); return FALSE; } static void setProxyURL(char *proxystring, char *proxyuserstring, char *proxypassstring) { if (proxyurl != NULL) { delete(proxyurl); proxyurl = NULL; } if (strlen(proxystring) > 2) { char *pxy = g_strdup_printf("http://%s/", proxystring); proxyurl = new URL(pxy, "", NULL, proxyuserstring, proxypassstring); g_free(pxy); } else { proxyurl = NULL; } } ////////////////////////////////////////////////////////////////////////////// // ReadAucFile: // called once at startup, reads the username and stored auctions from // ~/.bidwatcher/bw2.cfg // calls: ////////////////////////////////////////////////////////////////////////////// void ReadAucFile() { char fileName[200]; FILE *file; struct stat fstatus; memset(fileName, 0, sizeof fileName); sprintf(fileName, "%s/%s/bw2.cfg", getenv("HOME"), bw_subdir); if (stat(fileName, &fstatus)) { if (errno == ENOENT) { // Create it. file = fopen(fileName, "a"); fclose(file); } else { // Something else is wrong. perror("stat(bw2.cfg):"); return; } } file = fopen(fileName, "r"); if (file == NULL) { fprintf(stderr, "Error opening configuration file %s!\n",fileName); return; } while(!feof(file)) { char keyword[20]; fscanf(file, "%19s", keyword); if (feof(file)) break; if (!strcasecmp(keyword, "option")) { char which[20]; char recognized=0; fscanf(file, "%19s", which); if (!strcasecmp(which, "windowlocation")) { fscanf(file,"%d %d", &window_x, &window_y); retain_location = 1; recognized = 1; } if (!strcasecmp(which, "windowsize")) { fscanf(file,"%d %d", &window_width, &window_height); retain_size = 1; recognized = 1; } if (!strcasecmp(which, "tracklistings")) { fscanf(file, "%19s", which); if (which[0] == 'y' || which[0] == 'Y') trackListings = 1; else trackListings = 0; recognized = 1; } if (!strcasecmp(which, "trackbids")) { fscanf(file, "%19s", which); if (which[0] == 'y' || which[0] == 'Y') trackBids = 1; else trackBids = 0; recognized = 1; } if (!strcasecmp(which, "updateonstartup")) { fscanf(file, "%19s", which); if (which[0] == 'y' || which[0] == 'Y') doStartup = 1; else doStartup = 0; recognized = 1; } if (!strcasecmp(which, "autodelete")) { fscanf(file, "%19s", which); if (which[0] == 'y' || which[0] == 'Y') autoDelete = 1; else autoDelete = 0; recognized = 1; } if (!strcasecmp(which, "snipedelay")) { fscanf(file, "%i", &snipeDelay); recognized = 1; } if (!strcasecmp(which, "update_prio1_int")) { fscanf(file, "%i", &update_prio1_interval); recognized = 1; } if (!strcasecmp(which, "update_prio2_int")) { fscanf(file, "%i", &update_prio2_interval); recognized = 1; } if (!strcasecmp(which, "update_prio3_int")) { fscanf(file, "%i", &update_prio3_interval); recognized = 1; } if (!strcasecmp(which, "update_prio4_int")) { fscanf(file, "%i", &update_prio4_interval); recognized = 1; } if (!strcasecmp(which, "security")) { fscanf(file, "%i", &security); recognized = 1; } if (!strcasecmp(which, "timediff")) { fscanf(file, "%d", &timeDiff); clockIsSet = 1; recognized = 1; } if (!strcasecmp(which, "country")) { fscanf(file, "%i", &country); recognized = 1; } if (!strcasecmp(which, "browser")) { fscanf(file, " %[^\n]%*c", browserPATH); recognized = 1; } if (!strcasecmp(which, "emailclient")) { fscanf(file, " %199[^\n]", emailPATH); recognized = 1; } if (!strcasecmp(which, "proxy")) { fscanf(file, "%199s[^\n]", proxystring); recognized = 1; if (strspn(proxystring, " ") == strlen(proxystring)) proxystring[0] = '\0'; } if (!strcasecmp(which, "proxyuser")) { fscanf(file, "%199s[^\n]", proxyuserstring); recognized = 1; if (strspn(proxyuserstring, " ") == strlen(proxyuserstring)) proxyuserstring[0] = '\0'; } if (!strcasecmp(which, "proxypass")) { fscanf(file, "%199s[^\n]", proxypassstring); recognized = 1; if (strspn(proxypassstring, " ") == strlen(proxypassstring)) proxypassstring[0] = '\0'; } if (!strcasecmp(which, "fixedfont")) { fscanf(file, "%399s[^\n]", fixedFont); //gdk_font_unref(fixed_font); fixed_font = gdk_font_load(fixedFont); if (!fixed_font) { gdk_font_load(FONT_FIX_DFL); strcpy(fixedFont, FONT_FIX_DFL); } recognized = 1; } if (!strcasecmp(which, "cleanfont")) { fscanf(file, "%399s[^\n]", cleanFont); //gdk_font_unref(clean14); clean14 = gdk_font_load(cleanFont); if (!clean14) { gdk_font_load(FONT_CLEAN_DFL); strcpy(cleanFont, FONT_CLEAN_DFL); } recognized = 1; } if (!strncasecmp(which, "color", 5)) { int x=0; // Get the number of the color. x = atoi(which+5); #ifdef DEBUGCONFIG printf("x == %i (%s)\n", x, which+5); #endif fscanf(file, " %hi %hi %hi[^\n]", &colors[x]->red, &colors[x]->green, &colors[x]->blue); recognized = 1; } if (!recognized) DPRINTF(DHIGH, ("Unrecognized option %s\n", which)); } else if (!strcasecmp(keyword, "user")) { fscanf(file, "%s %s", authID, authPASS); if (strcmp(authPASS, "nopass") == 0) memset(authPASS, 0, sizeof(authPASS)); } else if (!strcasecmp(keyword, "auction")) { setProxyURL(proxystring, proxyuserstring, proxypassstring); char which[20]; auction[aucIdx] = new auctioninfo(); fscanf(file, LLU_FMT, &auction[aucIdx]->ItemNumber); while(!feof(file)) { fscanf(file, "%19s", which); if (!strcasecmp(which, "desc")) fscanf(file, " %120[^\n]", auction[aucIdx]->Description); else if (!strcasecmp(which, "comm")) fscanf(file, " %248[^\n]", auction[aucIdx]->Comments); else if (!strcasecmp(which, "ends")) fscanf(file, "%ld", &auction[aucIdx]->EndsValue); else if (!strcasecmp(which, "mybid")) { fscanf(file, "%f %d", &auction[aucIdx]->myBidAmount, &auction[aucIdx]->myBidQuantity ); #ifdef DEBUGCONFIG printf("read mybid %f\n", auction[aucIdx]->myBidAmount); #endif } else if (!strcasecmp(which, "endless")) fscanf(file, "%i", &auction[aucIdx]->isEndless); else if (!strcasecmp(which, "snipe")) { fscanf(file, "%f %d", &(auction[aucIdx]->snipeAmount), &(auction[aucIdx]->snipeQty)); #ifdef DEBUGCONFIG printf("read %.2f %d\n", auction[aucIdx]->snipeAmount, auction[aucIdx]->snipeQty); #endif setBid(auction[aucIdx], auction[aucIdx]->snipeAmount, auction[aucIdx]->snipeQty, true, false); } else if (!strcasecmp(which, "endauction")) break; } aucIdx++; } } fclose(file); setProxyURL(proxystring, proxyuserstring, proxypassstring); resetTimeSyncURL(); makeStyles(); resetStyles(); readBidGroup(bw_subdir); } static void PrintPrice(char *price, struct auctioninfo *auction) { char curbid[40]; bool is_dutch = strcmp(auction->HighBidder, "Dutch Auction") == 0; if(auction->CurrentBid > 0) { char flags[10] = ""; if (auction->reserveMet == 'n') strcat(flags, "R"); if (is_dutch) strcat(flags, "D" ); sprintf(curbid,"%s%.2f(%d%s)", auction->currency, auction->CurrentBid, auction->BidCount, flags); } char buynow[40]; if(auction->BuyitNowPrice > 0) { sprintf(buynow, "%s%.2f", auction->currency, auction->BuyitNowPrice); } if(auction->BuyitNowPrice > 0 && auction->CurrentBid > 0 && auction->BuyitNowPrice > auction->CurrentBid) { sprintf(price, "%s / %s", curbid, buynow); return; } if(auction->BuyitNowPrice > 0) { if (is_dutch) { sprintf(price, "%s(D,B)", buynow); }else{ sprintf(price, "%s(B)", buynow); } return; } if(auction->CurrentBid > 0) { sprintf(price, "%s", curbid); return; } strcpy(price," -"); } static void PrintMyBid(char *mybid, struct auctioninfo *auction) { if (auction->myBidQuantity) { sprintf(mybid, "%s%.2f", auction->currency, auction->myBidAmount); } else { strcpy(mybid, ""); } } ////////////////////////////////////////////////////////////////////////////// // UpdateListItem: // replaces the item in the index position with current information. ////////////////////////////////////////////////////////////////////////////// void UpdateListItem(int i) { char chTemp[20]; int intTimeLeft = stringTimeLeft(auction[i], timeDiff, chTemp); GdkColor *theColor; GtkStyle *bid_style; if (intTimeLeft < -30) theColor = &color_gone; else if (intTimeLeft < 14400) theColor = &color_near; else if ( strstr(auction[i]->Feedbackn,"NONE") != NULL) theColor = &color_none; else theColor = &color_far; if (auction[i]->isEndless) theColor = &color_near; // if there is a price, then there maybe flags to associate with it char price[80]; PrintPrice(price, auction[i]); char mybid[80]; PrintMyBid(mybid, auction[i]); gchar *item[] = { g_strdup_printf(LLU_FMT, auction[i]->ItemNumber), price, chTemp, mybid, auction[i]->Description, auction[i]->Seller, auction[i]->Feedbackn, auction[i]->Comments }; bidGroupComment(&item[7], auction, i); int j; for(j=0; jisSnipe) { gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, arrowPM, arrowmask); } else switch(auction[i]->stat) { case '1': gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, redledPM, redledmask); break; case '2': gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, greenledPM, greenledmask); break; case '3': gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, blueledPM, blueledmask); break; default: gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, blackledPM, blackledmask); break; } gtk_clist_set_foreground(GTK_CLIST(aucList), i, theColor); // Achieve alternating background colors gtk_clist_set_background(GTK_CLIST(aucList), i, (i%2)?&color_back2:&color_back1); // Set the bid cell's style bid_style = get_style(auction[i], i); gtk_clist_set_cell_style(GTK_CLIST(aucList), i, 3, bid_style); g_free(item[0]); } ////////////////////////////////////////////////////////////////////////////// // DeleteAuction: // deletes the auction at position index, adjust both the AucNumList[] // and auction[] to fill the gap created. // calls: // Clearauction() ////////////////////////////////////////////////////////////////////////////// void DeleteAuction(int index ) { CHECK; int idx; if (index >= aucIdx) return; // we are out of range delBidGroupItem(auction, index); // Loop through AucNumList, moving list up to fill the gap // where choice will be removed, this should be a linked list. WriteLog(index); delete auction[index]; for(idx = index ; idx < (aucIdx - 1 ); idx++) auction[idx] = auction[idx+1]; auction[aucIdx-1]=NULL; aucIdx--; CHECK; } /* gint getUserAuctions() { char address[1024]; char *Buff; int ret; showStatus("Checking My eBay"); sprintf(address, "http://signin.ebay.com/aw-cgi/eBayISAPI.dll?" "MfcISAPICommand=SignInWelcome&siteid=0&co_partnerId=2" "&UsingSSL=0&ru=http%%3A%%2F%%2Fcgi1.ebay.com%%2Faw-cgi%%2F" "eBayISAPI.dll%%3FMyEbayAll%%26first%%3DN%%26dayssince%%3D2" "%%26p1%%3D0%%26p2%%3D0%%26p3%%3D0%%26p4%%3D0%%26p5%%3D0%%26" "rows%%3D25%%26pagebid%%3D1%%26pagewon%%3D1%%26pagesell%%3D1" "%%26pagesold%3D1%%26pageunsold%%3D1%%26pagelost%%3D1%%26" "page%%3D1%%26all%%3D1%%26SaveSetting%%3D362413158%%26pass" "%%3D%%7B_pass_%%7D%%26userid%%3D&pp=pass&pa1=&pa2=&pa3=&" "i1=-1&pageType=368&userid=%s&pass=%s", authID, authPASS); URL *myurl = new URL(address, proxyurl); ret = fetchURL(myurl, 1, &Buff, TIMEOUT, 0); delete(myurl); printf("BUFF: %s\n", Buff); free(Buff); } */ ////////////////////////////////////////////////////////////////////////////// // // GetUserAuctions - grabs users auctions from ebay and adds them to // aucNum list if they aren't already there. // return -2 if userID is not recognized by ebay // return -1 if grab otherwise fails (lost connection, etc) // return -5 if the cgi server is down // return -4 on timeout // return 1 on success ////////////////////////////////////////////////////////////////////////////// int GetUserBids() { CHECK; bool flagMatch; int idx, cnt; char *Buff, *Buff2; char WebPage[200]; int returnVal; unsigned long long *ids; char cookiejar[200]; snprintf(cookiejar, (sizeof cookiejar) - 1, "%s/%s/cookies.txt", getenv("HOME"), bw_subdir); if (!trackBids) return GUA_SUCCESS; if (strlen(authID) < 2) return GUA_BADUSER; if (strlen(authID) > 64) return GUA_BADUSER; showStatus(" getting bids"); greenLED(); sprintf(WebPage, "http://cgi.ebay.com/aw-cgi/eBayISAPI.dll?" "MfcISAPICommand=ViewBidItems&userid=%s&completed=0&all=1&rows=200",// items the user has bid on authID); URL *bidsurl = new URL(WebPage, "", proxyurl); returnVal = fetchURL(bidsurl, 0, &Buff, cookiejar, 0); delete(bidsurl); blackLED(); showStatus(""); if ((returnVal != NET_SUCCESS)) { if (Buff) free(Buff); return ERROR; } if (strstr(Buff, "invalid") != NULL) { if (Buff) free(Buff); return GUA_BADUSER; } CHECK; Buff2 = parseRows(Buff); free(Buff); Buff = StripAndTab(Buff2); free(Buff2); ids = ParseList(Buff); //DPRINTF(DLOW, ("Buff=%s\n", Buff)); free(Buff); if (ids[0] == 0) { // This is OK, we just have no items bid on. free(ids); return GUA_SUCCESS; } CHECK; for (cnt=0; ids[cnt]!=0; cnt++) { if (aucIdx >= MAXAUCS) { free(ids); return GUA_SUCCESS; } flagMatch = FALSE; for (idx=0; idx < aucIdx; idx++) { if (auction[idx]->ItemNumber == ids[cnt]) auction[idx]->stat = '3'; if (auction[idx]->ItemNumber == ids[cnt]) updateitem(auction[idx]->ItemNumber); if (auction[idx]->ItemNumber == ids[cnt]) flagMatch = TRUE; } if (!flagMatch) addNewItem(ids[cnt]); CHECK; } CHECK; free(ids); return GUA_SUCCESS; } // end GetUserAuctions. void clearList(struct auctioninfo **list, int count) { for (int i=0; i < count+1; i++) { if (list[i] != NULL) delete(list[i]); } } ///////////////////////////////////////////////////////////////////////////// // GetUserListings - The auctions the user is selling. ///////////////////////////////////////////////////////////////////////////// int GetUserListings() { CHECK; char *Buff; char WebPage[256]; int returnVal; char cookiejar[200]; snprintf(cookiejar, (sizeof cookiejar) - 1, "%s/%s/cookies.txt", getenv("HOME"), bw_subdir); if (!trackListings) return GUA_SUCCESS; DPRINTF(DMED, ("Getting user listings.\n")); if (strlen(authID) < 2) return -1; if (strlen(authID) > 64) return -2; showStatus(" getting listings"); greenLED(); snprintf(WebPage, sizeof WebPage, "http://cgi6.ebay.com/ws/eBayISAPI.dll?ViewSellersOtherItems&userid=%s&sort=3&completed=0&since=-1&rd=1", authID); URL *listingurl = new URL(WebPage, "", proxyurl); returnVal = fetchURL(listingurl, 0, &Buff, cookiejar, 0); delete listingurl; blackLED(); showStatus(""); DPRINTF(DLOW, ("GetUserListings.returnval=%i\n", returnVal)); if (returnVal != NET_SUCCESS) { free(Buff); return ERROR; } if (strstr(Buff, "invalid") != NULL ) { free(Buff); return GUA_BADUSER; } // decision time. there are a lot of ways to do this. instead of taking the time // to strip the tags from the table, etc... we know that each item in the table // contains a link to the item's details. search through the html page for a // partial link match. once found copy just the URL part of the href. strip // the item number out of the URL. because it is possible that there are CRLF // in the URL, strip them out first and call addNewItem() with the auction // number. strip_crlf(Buff); const char *search_string = "http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem"; char *pszendurl; char *pszonlyurl; char *pszitemnumber; char *pszitemurl = strstr(Buff, search_string); while(pszitemurl != NULL) { // go forward until you find the next quote pszendurl = strchr(pszitemurl, '"'); if (pszendurl - pszitemurl <= 51) { // get the next url starting from the end of the current url. pszitemurl = strstr(pszendurl, search_string); continue; } // copy full url pszonlyurl = new char[pszendurl - pszitemurl + 1]; memset(pszonlyurl, 0, pszendurl - pszitemurl + 1); memcpy(pszonlyurl, pszitemurl, pszendurl - pszitemurl); pszitemnumber = strstr(pszonlyurl, "item="); if(pszitemnumber) { // addNewItem() checks for dups and for maximum number of auctions. // no need to do it twice. unsigned long long item; if(sscanf(pszitemnumber + 5, LLU_FMT, &item) == 1) addNewItem(item); } // delete the new'd memory delete pszonlyurl; // get the next url starting from the end of the current url. pszitemurl = strstr(pszendurl, search_string); } free(Buff); return GUA_SUCCESS; } /////////////////////////////////////////////////////////////////// ///////////------------------- UpdateList -------------//////////// /////////////////////////////////////////////////////////////////// void UpdateList() { if(!aucList) return; CHECK; char chTemp[20]; ArrangeList(); int intTimeLeft=0; GdkColor *theColor; GtkStyle *bid_style; gtk_clist_freeze(GTK_CLIST(aucList)); gtk_clist_clear(GTK_CLIST(aucList)); for (int i = 0; i < aucIdx; i++) { intTimeLeft = stringTimeLeft(auction[i], timeDiff, chTemp); if (intTimeLeft < -30) theColor = &color_gone; else if (intTimeLeft < 14400) theColor = &color_near; else if ( strstr(auction[i]->Feedbackn,"NONE") != NULL) theColor = &color_none; else theColor = &color_far; if (auction[i]->isEndless) theColor = &color_near; // if there is a price, the auction may have flags to associate with it char price[80]; PrintPrice(price, auction[i]); char mybid[80]; PrintMyBid(mybid, auction[i]); gchar *item[] = { g_strdup_printf(LLU_FMT, auction[i]->ItemNumber), price, chTemp, mybid, auction[i]->Description, auction[i]->Seller, auction[i]->Feedbackn, auction[i]->Comments }; bidGroupComment(&item[7], auction, i); gtk_clist_insert(GTK_CLIST(aucList), i, item); if (auction[i]->isSnipe) { gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, arrowPM, arrowmask); } else switch(auction[i]->stat) { case '1': gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, redledPM, redledmask); break; case '2': gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, greenledPM, greenledmask); break; case '3': gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, blueledPM, blueledmask); break; default: gtk_clist_set_pixtext(GTK_CLIST(aucList), i, 0, item[0], 5, blackledPM, blackledmask); break; } gtk_clist_set_foreground(GTK_CLIST(aucList), i, theColor); gtk_clist_set_background(GTK_CLIST(aucList), i, (i%2)?&color_back2:&color_back1); bid_style = get_style(auction[i], i); gtk_clist_set_cell_style(GTK_CLIST(aucList), i, 3, bid_style); g_free(item[0]); } gtk_clist_thaw(GTK_CLIST(aucList)); CHECK; return; } ////////////////////////////////////////////////////////////////////////////// // ArrangeList // // arrange the list in order of auction ending time. ////////////////////////////////////////////////////////////////////////////// void ArrangeList() { CHECK; struct auctioninfo * Scratch; int cnt = 0; bool swapflag = TRUE; while (swapflag) { swapflag = FALSE; for (cnt=0; cnt < (aucIdx - 1); cnt++) { if (auction[cnt]->EndsValue > auction[cnt + 1]->EndsValue) { Scratch = auction[cnt]; auction[cnt] = auction[cnt + 1]; auction[cnt + 1] = Scratch; swapflag = TRUE; } } } CHECK; } ////////////////////////////////////////////////////////////////////////////// // Updates the auction information for the AucListNum of the // index number passed. // Returns 1 success // Returns 2 connection problem // Returns 3 invalid auction (was deleted) // Returns 4 timeout // Returns 5 ebay cgi is down // Returns 6 itemNumber is out of bounds. // Returns 10 if the update was user-cancelled ////////////////////////////////////////////////////////////////////////////// int auctioninfo::getinfo() { CHECK; SetBidGroupAuction set_bid_group(auction, aucIdx, timeDiff, authID); int returnVal; char *HtmlBuff; char *urlstring; urlstring = g_strdup_printf("http://cgi.ebay.com/ws/eBayISAPI.dll" "?ViewItem&item="LLU_FMT, ItemNumber); if (infourl != NULL) { delete(infourl); infourl = NULL; } infourl = new URL(urlstring, "", proxyurl); greenLED(); returnVal = fetchURL(infourl, 0, &HtmlBuff, NULL, 0); if (returnVal == NET_NETERROR || returnVal == NET_TIMEOUT) { // maybe proxy settings changed if (infourl != NULL) delete(infourl); infourl = new URL(urlstring, "", proxyurl); free(HtmlBuff); returnVal = fetchURL(infourl, 0, &HtmlBuff, NULL, 0); if (returnVal == NET_NETERROR || returnVal == NET_TIMEOUT) { // Ok, so it probably is borked. g_free(urlstring); free(HtmlBuff); return returnVal | INFO_ERROR_RANGE; } } g_free(urlstring); blackLED(); // This looks majorly hacky to me, but lets at least free the memory // Thanks to kochc for pointing it out. if (returnVal != NET_SUCCESS) { if (HtmlBuff) free(HtmlBuff); return returnVal | INFO_ERROR_RANGE; } else if (strlen(HtmlBuff) < 1000) { free(HtmlBuff); return INFO_CGIDOWN; } // ok, html grab was a success - now process the html char *Buff; Buff = StripHtmlTags(HtmlBuff); if (HtmlBuff) free(HtmlBuff); #if defined(DEBUGGING) && DEBUGGING>DMED { FILE *fd; if ((fd = fopen("/tmp/bidwatcher-buf.txt", "a+")) != NULL) { fprintf(fd, "%s\n", Buff); fprintf(fd, "-- ---------------------- -- ---------------------- -- " "---------------------- \n"); fclose(fd); } } #endif // Check to see if this isn't really auction data. if (stristr(Buff, "Regularly Scheduled Maintenance")) { free(Buff); return INFO_CGIDOWN; } else if (stristr(Buff, "Please check the number and try again") || strstr(Buff, "Invalid Item")) { free(Buff); return INFO_BADAUCTION; } if (parseaucinfo(Buff)) { // if the grab was a success, check to see if it is a user // called auction. if (myBidQuantity) stat = '3'; if (strcmp(Seller, authID) == 0) { stat = '1'; } else { if (strcmp(HighBidder, authID) == 0) { stat = '2'; } else { for (int i=0; i < numbids; i++) { /* if (strcmp(ItemNumber, auctionlist[i]) == 0) { stat = '3'; } */ } } } free(Buff); UpdTime = time(NULL) + timeDiff; return INFO_SUCCESS; } free(Buff); return INFO_BADAUCTION; } /////////////////////////////////////////////////////////////////////////////// // TimeSync /////////////////////////////////////////////////////////////////////////////// void TimeSync() { CHECK; showStatus(" syncing clock"); int returnVal, i, tDiff; char *HtmlBuff; int new_timeDiff = -24*60*60; struct timeval tm_start, tm_end; double t1; // Strategy: Find our local time, and find eBay's time. Subtract. // Assume our local time is set properly. Even if it isn't, // we are only concerned with the difference. int num_good = 0; for(i = 0; i < 10 && num_good < 3; i++) { greenLED(); gettimeofday(&tm_start, NULL); resetTimeSyncURL(); returnVal = fetchURL(timesyncurl, 0, &HtmlBuff, NULL, 0); gettimeofday(&tm_end, NULL); t1 = (tm_end.tv_sec + 0.000001 * tm_end.tv_usec) - (tm_start.tv_sec + 0.000001 * tm_start.tv_usec); blackLED(); if (returnVal != 1) { #ifdef DEBUG_NETWORK fprintf(stderr, "Error (%d) fetching ebay's time web page, retrying... (%d)\n", returnVal, i); #endif continue; } if (t1 > 6) { #ifdef DEBUG_NETWORK fprintf(stderr, "Took too long (%.2f sec) to fetch ebay's time web page, retrying... (%d)\n", t1, i); #endif continue; } if (strlen(HtmlBuff) < 1000) { #ifdef DEBUG_NETWORK fprintf(stderr, "Short web page (%ld bytes) from ebay's time web page, retrying... (%d)\n", strlen(HtmlBuff), i); #endif continue; } tDiff = calcTimeDiff(HtmlBuff); free(HtmlBuff); // Network delays can cause the time returned by ebay to be // off, so we try to correct for this error by removing half the // total packet time. The time returned by ebay is (most likely) // truncated to the nearest second. We try to correct for this by // adding in a half second to "round" it correctly. #ifdef DEBUG_NETWORK fprintf(stderr, "Adjusting tDiff from %d by %.2f\n", tDiff, t1/2 + .5); #endif tDiff += (int)(t1/2 + .5); // is the time difference total garbage? if (tDiff < -24*60*60 || tDiff > 24*60*60) { #ifdef DEBUG_NETWORK fprintf(stderr, "Bogus tDiff (%d) from ebay's time web page, retrying... (%d)\n", tDiff, i); #endif continue; } if (tDiff > new_timeDiff) new_timeDiff = tDiff; num_good++; } #ifdef DEBUG_NETWORK if (num_good != i) fprintf(stderr, "Failed to get a good sync %d out of %d times\n", i - num_good, i); #endif time_t time_now = time(NULL); time_t gmt_time; int local_timeDiff; #if defined(HAVE_TM_ZONE) tzset(); gmt_time = time_now - mktime(gmtime(&time_now)); #elif defined(HAVE_GMTIME) /* This is not valid. (tm_gmtoff is a BSD-ism, not ANSI) struct tm * timeStruct = localtime(&time_now); gmt_time = timeStruct->tm_gmtoff; if (timeStruct->tm_isdst) { DPRINTF(DHIGH, ("Adjusted for DST\n")); gmt_time -= 60*60; // correct for daylight saving time } */ #elif defined(HAVE_TZNAME) // this may not work... localtime(&time_now); // just to set timezone global variable # if TIMEZONE_USABLE gmt_time = -timezone; # else # if UNDERSCORE_TIMEZONE_USABLE gmt_time = -_timezone; # endif # endif #else #error "Don't know how to get current timezone!" #endif // ebay is GMT-8hrs // BUT -7 during PDT! so this is a poor assumption. // (so if you are off by an hour in bw, try setting 8 to 7.) // How do we know when DST is in effect? local_timeDiff = -8*60*60 - gmt_time; // get real diff showStatus(""); // We only use the local_timeDiff if eBay is hosed. // It is likely to be wrong. if (num_good < 1) { clockIsSet = TRUE; timeDiff = local_timeDiff; // ebay is GMT+8hrs, but add a 5 minute fudge so that we bid // early to be safe // timeDiff += 5*60; showError("WARNING: Couldn't reach eBay, using local clock." " Do not depend on times or sniping."); return; } static bool warned_timeDiff = FALSE; if (abs(local_timeDiff - new_timeDiff) > 15*60) { // 15 minutes char msg[512]; sprintf(msg, "ERROR: System clock seems to differ from eBay's by" " %d minutes. Check system clock and timezone.", (local_timeDiff - new_timeDiff)/60); showError(msg); if (!warned_timeDiff) { sprintf(msg, "Using the local clock and timezone information to calculate\n" "eBay's time is %d minutes different than the time returned\n" "from eBay's web site. This may be a problem. Please\n" "double-check your system time and timezone.", (local_timeDiff - new_timeDiff)/60 ); new ErrorWindow(msg); warned_timeDiff = TRUE; } } #ifdef DEBUG_NETWORK if (clockIsSet && abs(new_timeDiff - timeDiff) > 2) fprintf(stderr, "Unusually large time change: %d - %d = %d\n", new_timeDiff, timeDiff, new_timeDiff - timeDiff); #endif clockIsSet = TRUE; timeDiff = new_timeDiff; #ifdef DEBUG_NETWORK fprintf(stderr, "TimeSync() time diff=%d local time diff=%d\n", timeDiff, local_timeDiff); #endif } void resetTimeSyncURL() { if (timesyncurl != NULL) { delete(timesyncurl); // must set it to NULL if we are testing for it above. timesyncurl = NULL; } timesyncurl = new URL("http://cgi3.ebay.com/aw-cgi/eBayISAPI.dll?TimeShow", "", proxyurl); } ///////////////////////////////////////////////////////////////////////////// // setupSnipe ///////////////////////////////////////////////////////////////////////////// void setupSnipe(struct auctioninfo * snipeAuction, int idx) { auction[idx] = snipeAuction; UpdateListItem(idx); WriteAucFile(); } ///////////////////////////////////////////////////////////////////////////// // WriteLog - append auction[index] to the completed auction log. ///////////////////////////////////////////////////////////////////////////// void WriteLog(int index) { if ((auction[index]->TimeLeft[0] != '0') && (CalcTimeLeft(auction[index]->EndsValue, timeDiff) < 0)) { ofstream reportOut; char fileName[200]; char *fnstring; fnstring = g_strdup_printf("/%s/log", bw_subdir); MakeFileName(fnstring, fileName, TRUE); reportOut.open(fileName, ios::app); char truncDesc[300]; sprintf(truncDesc,LLU_FMT" - %s\nHigh Bidder: %s%s\nHigh Bid: %s %.2f\nComments: %s\nSeller %s%s", auction[index]->ItemNumber,auction[index]->Description, auction[index]->HighBidder,auction[index]->BidderRate, auction[index]->currency,auction[index]->CurrentBid,auction[index]->Comments, auction[index]->Seller,auction[index]->SellerRate); strcat(truncDesc, "\n-----------------------------------------------------\n"); reportOut << truncDesc; reportOut.close(); //ClearSnipe(index); g_free(fnstring); } } /////////////////////////////////////////////////////////////////////////////////// ///// DoSnipe() /////////////////////////////////////////////////////////////////////////////////// void DoSnipe(int index) { char startTime[10]; char finishTime[10]; char *fnstring; ofstream reportOut; char fileName[200]; char truncDesc[1024]; int returnVal; printf("Trying to snipe with idx %i key %s amount %.2f quantity %d\n", index,auction[index]->snipeKey,auction[index]->snipeAmount, auction[index]->snipeQty); // now, submit the bid, then check the resulting buffer // for a message indicating it was successful: MakeClockTime(timeDiff, startTime); fnstring = g_strdup_printf("/%s/snipe", bw_subdir); MakeFileName(fnstring, fileName, TRUE); g_free(fnstring); reportOut.open(fileName, ios::app); sprintf(truncDesc, LLU_FMT" %s%.2f %s", auction[index]->ItemNumber,auction[index]->currency, auction[index]->snipeAmount, auction[index]->Description); greenLED(); returnVal = auction[index]->bid(FALSE); blackLED(); if (returnVal != NET_SUCCESS) { reportOut << "Bid processing failed: error " << returnVal << "\n"; // handled by eBayAgent // Try once more // greenLED(); // returnVal = auction[index]->bid(FALSE); // blackLED(); } MakeClockTime(timeDiff, finishTime); strcat(truncDesc, "\nSnipe start: "); strcat(truncDesc, startTime); strcat(truncDesc, " finish: "); strcat(truncDesc, finishTime); strcat(truncDesc, " auction ends: "); strcat(truncDesc, auction[index]->Ends); auction[index]->stat = '3'; switch(auction[index]->bidstatus) { case PB_HIGHBID: strcat(truncDesc, "\nSnipe completed: you are the high bidder!"); strcat(truncDesc, "\n---------------------------------------------------\n"); /* strcpy(auctionlist[numbids], auction[index]->ItemNumber); auction[index]->stat = '2'; */ numbids++; break; case PB_OUTBID: strcat(truncDesc, "\nSnipe completed: but you were outbid"); strcat(truncDesc, "\n---------------------------------------------------\n"); break; case PB_BIDTOOLOW: strcat(truncDesc, "\nSnipe failed: bid under the current asking price"); strcat(truncDesc, "\n---------------------------------------------------\n"); break; case PB_BADQUANTITY: strcat(truncDesc, "\nSnipe failed: problem with bid quantity"); strcat(truncDesc, "\n---------------------------------------------------\n"); break; case PB_AUCTIONOVER: strcat(truncDesc, "\nSnipe failed: auction ended before bid placed"); strcat(truncDesc, "\n---------------------------------------------------\n"); break; case PB_BADUSER: strcat(truncDesc, "\nSnipe failed: invalid username or password"); strcat(truncDesc, "\n---------------------------------------------------\n"); break; default: strcat(truncDesc, "\nSnipe failed: unknown reason"); strcat(truncDesc, "\n---------------------------------------------------\n"); } #ifdef DEBUG_NETWORK ofstream outFile; sprintf(fileName, "%s/%s/snipe_fail_"LLU_FMT, getenv("HOME"), bw_subdir, auction[index]->ItemNumber); outFile.open(fileName); outFile.close(); #endif reportOut << truncDesc; reportOut.close(); // ClearSnipe(index); WriteAucFile(); return; } ErrorWindow::ErrorWindow(char *message) { window=gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window),10); gtk_window_set_title(GTK_WINDOW(window),"Error"); messagelabel=gtk_label_new(message); gtk_widget_show(messagelabel); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),messagelabel, FALSE,FALSE,0); okbutton=gtk_button_new_with_label("OK"); gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", GTK_SIGNAL_FUNC (errorclose_callback), (gpointer) this); gtk_widget_show(okbutton); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),okbutton, FALSE,FALSE,0); gtk_widget_show(window); } ErrorWindow::~ErrorWindow() { if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); } ConfirmWindow::ConfirmWindow(char *message) { window=gtk_dialog_new(); gtk_container_set_border_width(GTK_CONTAINER(window),10); gtk_window_set_title(GTK_WINDOW(window),"Confirm"); messagelabel=gtk_label_new(message); gtk_widget_show(messagelabel); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),messagelabel, FALSE,FALSE,0); okbutton=gtk_button_new_with_label("OK"); gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", GTK_SIGNAL_FUNC (confirmok_callback), (gpointer) this); gtk_widget_show(okbutton); cancelbutton=gtk_button_new_with_label("Cancel"); gtk_signal_connect (GTK_OBJECT (cancelbutton), "clicked", GTK_SIGNAL_FUNC (confirmclose_callback), (gpointer) this); gtk_widget_show(cancelbutton); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),okbutton, FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area),cancelbutton, FALSE,FALSE,0); gtk_widget_show(window); } ConfirmWindow::~ConfirmWindow() { if (GTK_IS_WIDGET(window)) gtk_widget_destroy(window); } int main(int argc, char **argv) { gtk_init(&argc, &argv); // I think we don't really need getopt... // not using this for now. compile with -DDEBUGGING=# for now. // if (argc > 1 && !strcmp(argv[1], "-d")) dbug = TRUE; DPRINTF(DHIGH, ("Debugging Engaged...\n")); /* fixed_font = gdk_font_load("-*-nimbus roman no9 l-*-r-*-*-*-*-*-*-*-*-*-*"); clean14 = gdk_font_load("-*-courier-*-r-*-*-12-*-*-*-*-*-*-*"); */ fixed_font = gdk_font_load(FONT_FIX_DFL); clean14 = gdk_font_load(FONT_CLEAN_DFL); makeStyles(); init(); gtk_main(); // loop through the auction array and delete the // auctions before returning for(int i = 0; auction[i] != NULL; i++) { delete auction[i]; } // cleanup if(popupmenu != NULL) delete popupmenu; if(timesyncurl != NULL) delete timesyncurl; return 0; } void makeStyles() { int i; greenstyle = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { greenstyle->fg[i] = green; greenstyle->text[i] = green; greenstyle->bg[i] = black; greenstyle->base[i] = black; } greenstyle->font=fixed_font; yellowstyle = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { yellowstyle->fg[i] = yellow; yellowstyle->text[i] = yellow; yellowstyle->bg[i] = black; yellowstyle->base[i] = black; } yellowstyle->font=fixed_font; redstyle = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { redstyle->fg[i] = red; redstyle->text[i] = red; redstyle->bg[i] = black; redstyle->base[i] = black; } redstyle->font=fixed_font; wgreenstyle = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { wgreenstyle->fg[i] = green; wgreenstyle->text[i] = green; } wgreenstyle->font=fixed_font; wyellowstyle = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { wyellowstyle->fg[i] = yellow; wyellowstyle->text[i] = yellow; } wyellowstyle->font=fixed_font; wredstyle = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { wredstyle->fg[i] = red; wredstyle->text[i] = red; } wredstyle->font=fixed_font; clean14style = gtk_style_copy (gtk_widget_get_default_style()); clean14style->font=clean14; win_style = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { win_style->fg[i] = black; win_style->text[i] = black; } win_style->font=fixed_font; willwin_style = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { willwin_style->fg[i] = yellow; willwin_style->text[i] = yellow; } willwin_style->font=fixed_font; lose_style = gtk_style_copy (gtk_widget_get_default_style()); for(i=0;i<5;i++) { lose_style->fg[i] = red; lose_style->text[i] = red; } lose_style->font=fixed_font; /* Build all the clist cell styles we will need. This is helpful so that We don't have to malloc one for each cell and makes it so we don't waste 652 bytes everytime we lose track of one during the updates */ clist_willwin1 = gtk_style_copy(gtk_widget_get_default_style()); clist_win1 = gtk_style_copy(gtk_widget_get_default_style()); clist_lose1 = gtk_style_copy(gtk_widget_get_default_style()); clist_willwin1->fg[0] = color_willwin; clist_willwin1->text[0] = color_willwin; clist_willwin1->base[0] = color_back1; clist_willwin1->font=fixed_font; clist_win1->fg[0] = color_win; clist_win1->text[0] = color_win; clist_win1->base[0] = color_back1; clist_win1->font=fixed_font; clist_lose1->fg[0] = color_lose; clist_lose1->text[0] = color_lose; clist_lose1->base[0] = color_back1; clist_lose1->font=fixed_font; /* For the alternative background. */ clist_willwin2 = gtk_style_copy(gtk_widget_get_default_style()); clist_win2 = gtk_style_copy(gtk_widget_get_default_style()); clist_lose2 = gtk_style_copy(gtk_widget_get_default_style()); clist_willwin2->fg[0] = color_willwin; clist_willwin2->text[0] = color_willwin; clist_willwin2->base[0] = color_back2; clist_willwin2->font=fixed_font; clist_win2->fg[0] = color_win; clist_win2->text[0] = color_win; clist_win2->base[0] = color_back2; clist_win2->font=fixed_font; clist_lose2->fg[0] = color_lose; clist_lose2->text[0] = color_lose; clist_lose2->base[0] = color_back2; clist_lose2->font=fixed_font; } void resetStyles() { if (statuswindow) gtk_widget_set_style(statuswindow, greenstyle); if (statuslabel) gtk_widget_set_style(statuslabel, greenstyle); if (servertimelabel) gtk_widget_set_style(servertimelabel, greenstyle); if (ebtime) gtk_widget_set_style(ebtime, greenstyle); if (localtimelabel) gtk_widget_set_style(localtimelabel, greenstyle); if (aucList) gtk_widget_set_style(aucList, clean14style); } auctioninfo::auctioninfo() { memset(this, 0, sizeof(auctioninfo)); magic = 12345; isEndless = 0; UpdTime = 0; } auctioninfo::~auctioninfo() { magic = 789; delete(infourl); delete(bidurl); }