home *** CD-ROM | disk | FTP | other *** search
/ Dream 49 / Amiga_Dream_49.iso / beos / utils / skey-1.000 / SKey-1.4.3 / Source / Sources / SKeyView.cc < prev    next >
C/C++ Source or Header  |  1997-12-03  |  7KB  |  289 lines

  1. #include "SKeyMessage.h"
  2. #include "SKeyView.h"
  3.  
  4. #include "skey.h"
  5.  
  6. #include <interface/Font.h>
  7. #include <interface/View.h>
  8. #include <interface/TextControl.h>
  9. #include <interface/RadioButton.h>
  10. #include <app/Clipboard.h>
  11. #include <app/Looper.h>
  12. #include <app/MessageFilter.h>
  13. #include <kernel/OS.h>
  14.  
  15. #include <ctype.h>
  16.  
  17. PWFilter::PWFilter()
  18.          :BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE)
  19. {
  20.     pos = 0;
  21.     key[0] = '\0';
  22. }
  23.  
  24. filter_result PWFilter::Filter(BMessage *msg, BHandler **target)
  25. {
  26.     switch (msg->what) {
  27.     case B_COPY:
  28.     case B_PASTE:
  29.         return B_SKIP_MESSAGE;
  30.         break;
  31.     case B_KEY_DOWN:
  32.         int8 c;
  33.  
  34.         if (msg->FindInt8("byte", &c) != B_OK)
  35.             return B_SKIP_MESSAGE;
  36.  
  37.         switch (c) {
  38.         case B_TAB:
  39.         case B_ENTER:
  40.             return B_DISPATCH_MESSAGE;
  41.             break;
  42.         case B_BACKSPACE:
  43.             if (pos > 0)
  44.                 key[--pos] = '\0';
  45.             break;
  46.         default:
  47.             if (pos < KEY_LEN-1) {
  48.                 key[pos++] = c; key[pos] = '\0';
  49.                 msg->ReplaceInt8("byte", '*');
  50.             } else
  51.                 return B_SKIP_MESSAGE;
  52.         }
  53.  
  54.         return B_DISPATCH_MESSAGE;
  55.         break;
  56.     default:
  57.         return msg->WasDropped() ? B_SKIP_MESSAGE : B_DISPATCH_MESSAGE;
  58.     }
  59. }
  60.  
  61. void PWFilter::GetKey(char *dest)
  62. {
  63.     strcpy(dest, key);
  64. }
  65.  
  66. OTPView::OTPView(BRect frame)
  67.         :BView(frame, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
  68.                B_WILL_DRAW | B_FRAME_EVENTS)
  69. {
  70.     output_sem = create_sem(1, "output");
  71.     data[0] = '\0';
  72. }
  73.  
  74. void OTPView::AttachedToWindow()
  75. {
  76.     BView::AttachedToWindow();
  77.     BFont font_info;
  78.     GetFont(&font_info);
  79.     font_info.GetHeight(&font);
  80.     
  81. }
  82.  
  83. void OTPView::Draw(BRect update_rect)
  84. {
  85.     BRect bounds = Bounds();
  86.  
  87.     FillRect(update_rect, B_SOLID_LOW);
  88.  
  89.     // Draw a spiffy shaded rectangle.
  90.     SetHighColor(180, 180, 180);
  91.     StrokeLine(BPoint(0, 0), BPoint(0, bounds.bottom));
  92.     StrokeLine(BPoint(0, 0), BPoint(bounds.right, 0));
  93.     SetHighColor(240, 240, 240);
  94.     StrokeLine(BPoint(bounds.right, 0), BPoint(bounds.right, bounds.bottom));
  95.     StrokeLine(BPoint(0, bounds.bottom), BPoint(bounds.right, bounds.bottom));
  96.     SetHighColor(0, 0, 0);
  97.  
  98.     acquire_sem(output_sem);
  99.     DrawString(data, BPoint(5, bounds.top+
  100.                             (bounds.bottom+font.ascent)/2));
  101.     release_sem(output_sem);
  102. }
  103.  
  104. void OTPView::SetText(const char *string)
  105. {
  106.     if (!string || !*string)
  107.         return;
  108.  
  109.     acquire_sem(output_sem);
  110.     strncpy(data, string, sizeof(data));
  111.     release_sem(output_sem);
  112.     Draw(Bounds());
  113. }
  114.  
  115. void OTPView::MouseDown(BPoint point)
  116. {
  117.     BMessage msg(B_MIME_DATA);
  118.     const char *data = Text();
  119.     msg.AddData("text/plain", B_MIME_TYPE, (void *)data,
  120.                  strlen(data));
  121.     DragMessage(&msg, BRect(Bounds()));
  122. }
  123.  
  124. const char *OTPView::Text()
  125. {
  126.     return data;
  127. }
  128.  
  129. SKeyView::SKeyView(BRect frame, const bool md)
  130.          :BView(frame, NULL, B_FOLLOW_ALL_SIDES,
  131.                 B_WILL_DRAW | B_FRAME_EVENTS)
  132. {
  133.     md4 = md;
  134. }
  135.  
  136. void SKeyView::AttachedToWindow()
  137. {
  138.     BRect bounds = Bounds();
  139.     rgb_color PWColor = { 255, 255, 255, 0 };
  140.  
  141.     SetViewColor(235, 235, 235);
  142.  
  143.     // Create all the sub-views here.
  144.     SeedView = new BTextControl(BRect(5, 3, bounds.right-5, 20), NULL,
  145.                                 SEED_PROMPT, NULL, new BMessage(SKEY_COMP_KEY));
  146.     AddChild(SeedView);
  147.     SeedView->SetDivider(SeedView->StringWidth(SEED_PROMPT)+10);
  148.  
  149.     PWView = new BTextControl(BRect(5, 25, bounds.right-5, 42), NULL, KEY_PROMPT, NULL,
  150.                            new BMessage(SKEY_COMP_KEY));
  151.     filter = new PWFilter;
  152.     PWView->TextView()->AddFilter(filter);
  153.     PWView->TextView()->MakeSelectable(false);
  154.     AddChild(PWView);
  155.  
  156.     PWView->SetDivider(SeedView->StringWidth(KEY_PROMPT)+10);
  157.  
  158.     BRadioButton *radio_button = new BRadioButton(BRect(bounds.right-BUTTON_WIDTH-5, 50,
  159.                                                             bounds.right-85, 65), NULL,
  160.                                                      "MD4", new BMessage(MD4_MSG));
  161.     AddChild(radio_button);
  162.     if (md4)
  163.         radio_button->SetValue(B_CONTROL_ON);
  164.  
  165.     BRect frame = radio_button->Frame();
  166.     frame.left = frame.right + 5; frame.right = bounds.right-5;
  167.     radio_button = new BRadioButton(frame, NULL, "MD5", new BMessage(MD5_MSG));
  168.     AddChild(radio_button);
  169.     if (!md4)
  170.         radio_button->SetValue(B_CONTROL_ON);
  171.  
  172.     // Put a box around the password view.
  173.     BBox *pw_box = new BBox(BRect(5, 50, 5+OTP_BOX_WIDTH, 50+OTP_BOX_HEIGHT));
  174.     pw_box->SetLabel("S/Key Password");
  175.     pw_box->SetViewColor(235, 235, 235);
  176.     pw_box->SetLowColor(235, 235, 235);
  177.     pw_box->SetFont(be_plain_font);
  178.     AddChild(pw_box);
  179.  
  180.     // Create the view for the One Time Password.
  181.     BFont font;
  182.     font_height font_height;
  183.     pw_box->GetFont(&font);
  184.     font.GetHeight(&font_height);
  185.     KeyView = new OTPView(BRect(5, font_height.ascent+font_height.descent,
  186.                                  OTP_BOX_WIDTH-5, OTP_BOX_HEIGHT-5));
  187.     pw_box->AddChild(KeyView);
  188.  
  189.     // Now add the button.
  190.     BButton *button = new BButton(BRect(bounds.right-BUTTON_WIDTH-5, 68,
  191.                                   bounds.right-5, 0), NULL, BUTTON_LABEL,
  192.                                   new BMessage(SKEY_COMP_KEY));
  193.     AddChild(button);
  194.  
  195.     SeedView->MakeFocus();
  196. }
  197.  
  198. void SKeyView::MessageReceived(BMessage *msg)
  199. {
  200.     switch (msg->what) {
  201.     case MD4_MSG:
  202.         md4 = true;
  203.         break;
  204.     case MD5_MSG:
  205.         md4 = false;
  206.         break;
  207.     case B_COPY: {
  208.         const char *data = KeyView->Text();
  209.         if (!data || !*data)
  210.             return;
  211.         be_clipboard->Lock();
  212.         be_clipboard->Clear();
  213.         be_clipboard->Data()->AddData("text/plain", B_MIME_TYPE, (void *)data,
  214.                                        strlen(data));
  215.         be_clipboard->Commit();
  216.         be_clipboard->Unlock();
  217.         SeedView->MakeFocus();
  218.     }; break;
  219.     case B_PASTE: {
  220.         const char *data;
  221.         ssize_t length;
  222.         be_clipboard->Lock();
  223.         be_clipboard->Data()->FindData("text/plain", B_MIME_TYPE, 0, &data, &length);
  224.         be_clipboard->Unlock();
  225.         if (!data || !*data)
  226.             return;
  227.         SeedView->SetText(data);
  228.     }; break;
  229.     case SKEY_COMP_KEY: {
  230.         char key[KEY_LEN];
  231.         const char *seed = SeedView->Text();
  232.         filter->GetKey(key);
  233.         char *otp = ComputeKey(seed, key, md4);
  234.         KeyView->SetText(otp);
  235.     }; break;
  236.     default:
  237.         BView::MessageReceived(msg);
  238.     }
  239. }
  240.  
  241. bool SKeyView::GetMD()
  242. {
  243.     return md4;
  244. }
  245.  
  246. char *ComputeKey(const char *seed, const char *key, bool md4)
  247. {
  248.     if (!seed)
  249.         return NULL;
  250.  
  251.     char *bogon, number[10], crunched[128];
  252.     static char otp8[64];
  253.  
  254.     // Ignore everything before the first digit.
  255.     for (; *seed && !isdigit(*seed); seed++);
  256.  
  257.     if (!*seed)
  258.         return NULL;
  259.  
  260.     // Set the seed index to the first non-digit after that.
  261.     long i;
  262.     for (i=0; i < sizeof(number) && *seed && isdigit(*seed); seed++) {
  263.         number[i] = *seed; i++;
  264.     }
  265.     number[i] = '\0';
  266.  
  267.     if (!*seed)
  268.         return NULL;
  269.  
  270.     int iter = strtol(number, &bogon, NULL);
  271.  
  272.     // Skip the white space.
  273.     for (; seed && *seed && isspace(*seed); seed++);
  274.  
  275.     if (md4) {
  276.         md4_keycrunch(crunched, (char *)seed, (char *)key);
  277.         for (; iter > 0; iter--)
  278.             md4_f(crunched);
  279.     } else {
  280.         md5_keycrunch(crunched, (char *)seed, (char *)key);
  281.         for (; iter > 0; iter--)
  282.             md5_f(crunched);
  283.     }
  284.  
  285.     // If you really like hex output, uncomment the line below.
  286.     // return put8(otp8, crunched);
  287.     return btoe(otp8, crunched);
  288. }
  289.