194
points
A few months ago, I spent a couple days reverse engineering the Snapchat protocol and wrote a quick and dirty library to use it in your own PHP apps:
https://github.com/tlack/snaphax
Today Snapchat has written me requesting that I take it offline:
Hi Thomas,
I'm writing to ask that you remove Snaphax from github
and no longer publish or distribute it. Snapchat does
not permit third party software to access our API and
we consider Snaphax to be an unlawful circumvention
device under 17 U.S.C. § 1201(a)(1).
Please confirm that it has been removed by end of day
Monday, July 22nd.
Thank you,
Micah Schaffer
Snapchat, Inc.
I haven't had much time to really finish Snaphax (and I doubt I ever will) but I strongly support the idea that third party software should be able to interact with the services I use every day.I am under the impression that reverse engineering is still protected under fair use doctrines. Is this the case? How should I respond, if at all?
Snapchat provide a service, which I mentioned in another comment here that they have every right to enforce terms of service on, and restrict or allow usage as they see fit.
Snapchat also provide an API (which, in this scenario can also be considered a network protocol). This API can be used to access this service.
Now that I've had a look at the code, I've noticed that it includes the API keys which grant programs using this library the appropriate access permissions for the service. I think this is wrong, and that these keys should not be included in an open source library. The rest of the code however, is fine, as it simply implements a protocol.
If I were to develop something like this, I would leave out the API keys and have the user of the library fill them in. In principle, and as someone else has mentioned here, it would be possible to develop and operate your own service which uses this protocol/API. And I see nothing wrong with that.
Well, except of course that the whole notion of an app which presents information for a set period of time after which the user can no longer view it is inherently flawed, since eventually someone's going to figure out how to not erase/hide the information.
As with file formats, the notion that network protocols & APIs should ever be granted any type of protection and that no-one other than the creators should be able to write software that conforms to these protocols is ridiculous.
Snapchat, in my view, have every right to restrict who uses their service and in what manner - via standard mechanisms like API keys and login credentials. But preventing third-party implementations of protocols or APIs is so 90s. Oracle had a bit of trouble with this recently.
One problem I'm personally trying to remedy is the proliferation of various APIs and protocols for accessing various online storage services (Dropbox, Google Drive, Box etc) by developing an SDK that supports all of them. We need more of this kind of these kinds of projects, not less.
Micah Schaffer, if you're reading this, you're welcome to send me a takedown request and discuss the issue with me. My email address is in my profile.
EDIT: It's at 62 now. I wouldn't be surprised if even Barbra Streisand has forked it.
https://twitter.com/ansimionescu/status/359361709904891904
Edit: Why not use some of these https://www.google.com/search?q=pro+bono+lawyer+advice
I think the impending 3Taps (padmapper.com) v/s Craigslist case[1] will shed more light on this. padmapper were using Craigslist data that is 'freely available' and Craigslist didn't like it.
[1] http://www.dmlp.org/threats/craigslist-v-3taps
Any access to or use of craigslist to design, develop, test, update, operate, modify, maintain, support, market, advertise, distribute or otherwise make available any program, application or service (including, without limitation, any device, technology, product, computer program, mobile device application, website, or mechanical or personal service) that enables or provides access to, use of, operation of or interoperation with craigslist (including, without limitation, to access content, post content, cross-post content, re-post content, respond or reply to content, verify content, transmit content, create accounts, verify accounts, use accounts, circumvent and/or automate technological security measures or restrictions, or flag content) is prohibited.
I don't believe they can (or perhaps "should be allowed to") stop people from accessing their site via http (which is a protocol or api). Either way, it feels the same to me; I think it's relevant.
Assuming the posted letter is complete, a lawyer can't really do anything at this point. The letter (or is it actually an email?) doesn't invoke any requirements one is bound by law to obey. One might even say that it's careful not to do so, so I suspect that even though the "Director of Operations" signed it, it was originally written by a lawyer. This would actually be a useful form letter for people who have their underpants on a bit too tight: even if they send it five times a month, it doesn't create any sort of SLAPP liability or anything else that will damage Snapchat in a legal sense. Of course, giving someone 12 hours to comply with anything looks like amateur hour. tlack isn't the only party reluctant to run up billable hours.
IANAL. If I were, I would recommend you start paying me or one of my colleagues to talk with you immediately.
You do not need to wait until you are sued or prosecuted to get advice from a lawyer.
They say "we consider Snaphax to be an unlawful circumvention device under 17 U.S.C. § 1201(a)(1)."
They are implying he would be subject to lawsuit and/or criminal prosecution if he keeps distributing the software.
How likely is that to happen? How risky is it for the guy? How expensive might the defense be, and how much pain might this be for a weekend project?
I'm not really sure. But you know what class of people are expert at answering questions like that? Lawyers.
But, sure, if the poster want to keep it up anyway cause you think it's bullshit and are willing to see what they do next, certainly that's another option. It's potentially a brave and commendable one.
But I wouldn't do it because a bunch of people on HN who don't know what they're talking about told me that since they didn't use some special magic words in the letter, there's "nothing a lawyer can do", what?
A lawyer can analyze the facts of what you have done, and provide you with advice as to whether it is likely to be found to be an anti-circumvention device under the cited section of the DMCA and, if so, what the likely consequences of that are and what steps you can take to mitigate any exposure you might have in that regard (including, if there are any, steps short of taking down the existing offering.)
Of course, you could wait to see if they actually file a suit rather than having a lawyer look at the C&D, but if you do that, then there will be less, not more, that a lawyer can do for you.
At this point in time, OP can take down the repo (but not the 115-and-counting forks thereof), or modify it (someone suggested removing keys issued by Snapchat), or not. How will this set of options change if Snapchat file suit? Of course one must respond to a suit, but couldn't one's response be "ok we've complied with all requests"?
If you're telling me that the suit could allege OP owes Snapchat money for his/her misdeeds, that's true, but it's always true, even after one complies with the sort of namby-pamby "C&D" we see here.
For what it is worth, we were given a few days in a cease and desist letter recently and our $250/hr lawyer laughed at the idea of just a few days notice. 12 hours or even a few days now doesn't seems serious at all.
> I am under the impression that reverse engineering is still protected under fair use doctrines. Is this the case? How should I respond, if at all?
Speaking as someone who has been involved in an arduous civil matter for the last four years, matmaroon's advice would be well heeded.
"There's no way they can sue you for that."
"No way a judge will even allow this case."
"This case will be dismissed after the first hearing."
When someone sends you a letter like this, the first decision you have to make is "how much is this thing worth to me". Once you've decided that it's worth fighting for, your best counsel will come from a lawyer, who can help you determine the thing that really matters: how much it's going to cost you.
In general, though, not taking it down will be a tough path for you.
If you really want to go down that path, get a lawyer (i'm happy to make recommendations for you), say nothing else here (or anywhere) about your motivations/goals/whatever, and go that way.
If you don't want to spend the time or the money, take it down .
So if you want to resist, you could start there: by finding out (possibly by asking a lawyer to talk to them) how they think your tool is acting to "descramble a scrambled work, decrypt an encrypted work, (or equivalent actions)". If you want to do this, you might consider reaching out to the EFF for help.
Morally, I think you're in the clear for the reason you already gave.
And here's an article from the EFF with a few citations of cases where DMCA article 1201 has been used: https://www.eff.org/es/wp/unintended-consequences-under-dmca
Well, the specific thing the DMCA does is to stop circumvention of an "effective technological protection measure". The crazy thing here is that there is no such measure: no use of encryption or scrambling -- or even passwords! -- that I can see, just simply using a network service's exposed command set. That makes it different to most (if not all) of the case law your link mentions.
So this is definitely one of those occasions that legal advice is required, not moral advice.
If they shipped the app/service without a "force the user to update" feature, they would risk leaving thousands of users in the dark.
And if they did modify their protocol, it would probably get reverse-engineered again, either by the OP or somebody else.
Another alternative is to mail them back and ask them for clarification. Why do they consider it an infringement?
The law clearly states the following:
The way I interpret this is that if one is overcoming some encryption or authentication scheme, it may be disallowed under the law. If one is simply observing a protocol online, then one may be doing something bad as this says.At least for me any EULAs that aren't signed before purchase (i.e., all shrinkwrap or clickthrough "agreements") aren't binding unless I choose to - B2B sales with explicit signed contracts would be binding; or if I want to do something that by law requires permission (i.e., redistribution instead of just using the software) then I might accept an 'EULA' such as GPL.
EULA is regarded as a contract in "most" (or all?) jurisdictions, and as such, depend on contract law to define what is allow and what isn't. EULA's is also regulated under consumer protection laws. Since each state in the USA have slightly different kind of consumer protection and contract law, one would really need to dig down into the law books to decide if the EULA is at all legally binding in a specific state.
But I have one correction to mention. Copyright licenses are not viewed as contract in the USA. Copyright licenses like GPL are granted permissions, waiving the right to sue distributors under specific situation. If the distributor get sued for distributing GPL software, then it is she who must raise the license as protection. "I got right to distribute this copyrighted work, because I received this license who says I can". The license "terms" only specifies under what situation permission have been given.
In EU however, licenses are contract and under contract law. As such, the permission to distribute can be revoked if contract law has been violated.
Not insofar as the reverse engineering is used to produce an anti-circumvention device under the DMCA (that is, the reverse engineering itself is still just as protected as it used to be, but that protection does not extend to making the anti-circumvention device available.)
Note that there is still the issue of whether what you've actually is an anti-circumvention device.
> How should I respond, if at all?
If the project is worth the cost of consulting a lawyer, you very likely should do that so you understand better what your exposure here is and can make a more informed decision than you would be able to make based on lay advice you might get from HN. If its not, you should probably take it down.
If you need legal advice, I recommend seeing if SFLC (http://www.softwarefreedom.org/) will help you. In the past, I worked on a free software project where we willfully ignored a cease and desist notice and got sued by a large multinational corporation, and they were awesome.
However, while you may not be able to distribute software which uses the API, I think many people would enjoy/benefit from a post describing how you reversed it and what steps you took to create the library.
I don't know anything about the Snapchat API but if it's simply undocumented I don't see how that would be a "technological measure" of "effective control."
If you had to sniff or crack an API key of some sort, maybe that does.
In any event, it seems like a friendly enough request, maybe take it down as a courtesy pending their clarifying exactly what "technological measure" of "effective control" they think it "circumvents." Depending on their response and how much you think you want to push it, you can then decide what to do.
I'd ignore it. If they want to go hard-ball they'll threaten to sue/actually sue. Until then keep silent.
It is all well and good to write these sorts of things as a demo, but distribution is something where I would defer to the actual owner of the API in question.
After all, how many of us would want someone creating an unauthorized library to a private API that we don't wish to have public?
https://www.eff.org/deeplinks/2012/05/no-copyrights-apis-jud...
Snapchat developed the service and the API. They don't want alternative implementations of the API to access their service. Morally, publishing such an alternative implementation is questionable. At best, it is discourteous in the extreme.
If someone asks you not to copy the product of their creative work, what moral justification do you have for doing so?
You have raised a very good point though, and it's certainly made me revisit my take on this. I've personally been the victim of others taking copies of my app and selling it under different names (which I obviously do have a problem with). However I've also seen other people implement similar features and a similar UI to my own app, and I don't have a problem with that - we only got to where we are today because of the spread of ideas through these means (see: Xerox PARC and all the companies that have used their work).
In this particular case there was no IP violation. It was simply an alternative implementation of a network protocol - and in fact it was just a library, not an application in and of itself. The only thing I think the author did wrong was to include the API keys.
I would agree with your position if this was some internal service of theirs.
First, I'd ask myself how much I care about this. Do I care enough to pay legal fees to defend myself if Snapchat decides to come after me? If yes, consult an attorney and find out what you're looking at. Ignore any legal advice you get here. Unless it's from an actual attorney on your payroll (and attorneys you aren't paying won't give you much beyond an initial consultation)
If no, you've got an easy choice: take it down.
It _may_ indeed be illegal under the DMCA to distribute. Or it may be legal, as there are some exceptions for reverse engineering etc.
Nobody here knows. Heck, even a lawyer might not know, but a laywer will know your level of legal risk and possible expense.
Edit: after some research (like reading TFRepo), I found some links mentioned that give some info in case anyone else is curious too.
http://adamcaudill.com/2012/06/16/snapchat-api-and-security/
https://github.com/tlack/snaphax#motivation-and-development-...
Lackner: Mr. Schaffer, are you a lawyer? Please elaborate on why you consider Snaphax to be unlawful circumvention. I will assess the merits of your argument and then make a decision.
While people in this thread all give the customary knee-jerk "get a lawyer" response, consider that:
1. The request did not come from Snapchat's lawyers, if they have any retained for the purpose of DMCA claims. Surely they must, right?
2. It does not state what happens if Lackner does not comply. There's no threat of legal action. It just asks Lackner to remove the code from Github.
As such, there's no reason not to ask Schaffer to clarify why he thinks there is a problem.
If lawyers are not involved yet, then asking questions is free.
If this was a clear DMCA violation, then why didn't Schaffer send this to Snapchat's lawyers to handle?
Maybe because he might not get the answer he wanted: that it's a clear DMCA violation and an easy win for Snapchat.
Any lawyer can be asked to send a threatening DMCA violation letter. They will almost always say, "Yes, we can do that for you."
But sending a threatening letter does not mean it's a slam dunk win if the recipient does not comply with the demands in the letter. Sometimes threats are hollow. The sender may have no intention of pursuing litigation any further than sending demand letters. It simply might not be worth the money to pursue litigation over something like Snaphax. If this bit of PHP was that big of a deal to Snapchat, why didn't the request to remove it from Github come from Snapchat's lawyers? Where's the line about purusing all legal remedies?
Not to mention that by sending a threatening letter with no details on why the sender thinks the code at issue is a DMCA violation, there's a risk that the recipient might post a link to the code on HN and set off a "Github fork bomb". Ouch.
But, I personally wouldn't worry about it. If they really felt strongly they would send something to GitHub asking to have your project removed. If GitHub takes it down that means they are either being douchey and covering their butts, or they believe the request has legal merit.
There's the statute, for you armchair quarterback-lawyers out there.
If you reverse engineered rather than copied from Docs or header files I don't believe it should be copyright infringement. Note that the Google Oracle case currently being appealed seems wrong to me as I think copyright on complicated API's are reasonable (many disagree with me) although fair use and antitrust arguments should in many cases allow reimplementation. Anyway in statutory terms I don't see a problem. However...
It is likely that you agreed to Snapchat's terms of service at some point and it is also likely (I haven't read them) that they contain clauses forbidding permission to reverse engineer and/or access the service without using official clients. This opens up possibilities for breach of contract legal action and more worryingly computer crimes prosecution for unauthorized access. This conversion of minor contract breaches into computer hacking crimes is horrible law but it seems to be current reality. Be careful.
I don't know if you are in a better or worse position if you use the software without agreeing to the terms and conditions.
actually went the other way, but Chamberlain's argument was an interesting one: the copyright-able "work" was the code that ran in the garage door opener that actually opened the door. That code was protected against running (access in 1201 a) by the remote's code system.
The judge got access to the code v. access to the customer's garage mixed up and ruled against Chamberlain because it seemed silly. The DMCA is that silly, though and extreme unintended effects cases like this are the way to get support to re-write digital-age copyright.
Here, there are two access controls (control over access to running (accessing) copyrighted code on Snapchat's server) in question: the API key and use of that key. Is supplying one part of a circumvention device (the library) without the other (the API key) still a 1201 a violation? Patent law has provisions against "independent" manufacturers supplying parts that together violate a patent, but alone do not. MGM v. Grokster already tried to bring some of that reasoning into copyright (case) law. http://en.wikipedia.org/wiki/Inducement_rule
The less interesting, but more dangerous to the O.P. question is the T.O.S. violation. Pure reverse engineering is done without access to documentation about the thing reversed. Purest has two teams: one to analyze and write an expression-independent specification and another to implement that spec.
> Please confirm that it has been removed by end of day Monday, July 22nd.
Essentially, they're giving the poster less than a full day to act on this. That strikes me as a high pressure tactic on Snapchat's part designed to get the poster into pulling that library before taking the time to consult with an attorney.
130 forks and counting.
I would seek a lawyer if you can afford one and if not, then you can't afford a lawsuit either, so in this case, pull it offline. If you do the latter, you should post the results of your research somewhere, this can't be taken down as it is sharing information and not an API tool.
When you signed up you will have agreed not to do this sort of thing in the terms and conditions - whether that is legally enforceable or not could be expensive to prove either way. Though the worst they can do you for here is breach of contract.
With regard to "copyright circumvention": un-rot13 has been classed as an encryption circumvention device before now, so don't bank on the law having any common sense here.
My advice:
1. If it is just a weekend project it isn't worth the hassle, drop it as requested.
2. If you really care about it, lawyer up and prepare to fight.
In either case post to HN and as many other places as you can that are relevant to make sure their status as litigious wankers is recorded as far and wide as possible ;-)
While the idea of getting the word out there that these people are idiots is amiable, it's not the best idea legally. Now they can prove that you saw their original email and probably have scumbag lawyers who can use this post in other ridiculous ways (claim it proves malicious intent, for instance... no idea what they'd actually do).
http://en.wikipedia.org/wiki/United_States_v._ElcomSoft_and_...
https://github.com/bholzer/RubySnap/blob/master/rubysnap.rb
I persume they can't file a lawsuit without filing DMCA takedown notice first?
If so, when they'll file the notice, GitHub'll take it down (as they usually do). Then you may consider filing counter-notice (if you can afford legal action) or, I guess (IMNAL!) ignore the whole affair.
Anyway, you'd better consult a lawyer.
DMCA notices -- by which, presumably, you mean takedown notices -- are only required to a third-party that is otherwise within the DMCA safe harbor protecting hosts of allegedly-copyright-infringing user-submitted content to choose either to take the content down or forfeit the protection of the safe harbor. They have nothing to do with actions against direct violators of either the main body of copyright law or the anti-circumvention provisions of the DMCA.
> I persume they can't file a lawsuit without filing DMCA takedown notice first?
You presume incorrectly; even if the alleged violation was of the type to which a DMCA takedown was relevant, they can sue the offending party (though not a third-party host within the safe harbor) without a takedown notice.
Technically, it wouldn't be utilizing their API, it would just be a PHP library for accessing APIs that happen to use their exact API call structure.
I know it's a long shot, and it may not hold up, but I think it's better than just taking it down.
You've already got a client library written--why not go ahead and post up a conforming backend as well? If you want, shoot me an email with your doc'ed API, and I'll shoot you back (gimme a week--things on fire right now) a simple Sinatra mockup.
Clean room all the things!
EDIT:
For an idea of a quick hack of this variety, see my work from last week -- https://www.hackerneue.com/item?id=6065652
#include "stdafx.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif
///////////////////////////////////////////////////////////////////////////// typedef struct {BYTE lo,hi;} BYTE_BYTE; typedef struct {WORD lo,hi;} WORD_WORD; typedef struct {BYTE b0,b1,b2,b3;} FOUR_BYTES; typedef union {BYTE_BYTE b; WORD w;} BYTE_WORD; typedef union {WORD_WORD w; DWORD d; int i; FOUR_BYTES b;} WORD_LONG;
///////////////////////////////////////////////////////////////////////////// #define ct_GetTickCount 0 #define ct_high_performance 1 #define ct_multimedia 2 //Not yet implemented
int counter_type=ct_GetTickCount; double high_performance_counter_frequency;
void init_counter() { LARGE_INTEGER freq; if (QueryPerformanceFrequency(&freq)) { high_performance_counter_frequency=freq.LowPart+ freq.HighPart65536.065536.0; counter_type=ct_high_performance; } else counter_type=ct_GetTickCount; }
///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About
class CAboutDlg : public CDialog { public: CAboutDlg();
// Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA
// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL
// Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() };
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT }
void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP }
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// // CInGodsTimeDlg dialog
CInGodsTimeDlg::CInGodsTimeDlg(CWnd* pParent /=NULL/) : CDialog(CInGodsTimeDlg::IDD, pParent) { //{{AFX_DATA_INIT(CInGodsTimeDlg) m_main = _T(""); m_max = 100109; m_max_changed=false; //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_num=1; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); }
void CInGodsTimeDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CInGodsTimeDlg)
DDX_Text(pDX, IDC_MAIN, m_main); DDX_Text(pDX, IDC_MAX, m_max); DDX_Text(pDX, IDC_NUMB, m_num); //}}AFX_DATA_MAP }
BEGIN_MESSAGE_MAP(CInGodsTimeDlg, CDialog) //{{AFX_MSG_MAP(CInGodsTimeDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_STOP, OnStop) ON_BN_CLICKED(IDC_CHOICE_WORDS, OnChoiceWords) ON_BN_CLICKED(IDC_CHOICE_NUMBERS, OnChoiceNumbers) ON_BN_CLICKED(IDC_SELECT_WORDS, OnSelectWords) //}}AFX_MSG_MAP END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// // CInGodsTimeDlg message handlers
BOOL CInGodsTimeDlg::OnInitDialog() { CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } }
// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
}void CInGodsTimeDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } }
// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.
void CInGodsTimeDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting
}// The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CInGodsTimeDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; }
// long fsize(FILE f) { long result,original=ftell(f); fseek(f,0,SEEK_END); result=ftell(f); fseek(f,original,SEEK_SET); return result; }
WORD hash_string(const char src) { BYTE_WORD sum; sum.w =0; while (src) { sum.w += ((src++)); sum.w <<=1; } sum.w += sum.b.hi; return sum.w; }
char malloc_string(const char src) { int len=strlen(src); char result=(char )malloc(len+1); strcpy(result,src); return result; }
#define pm_numbers 0 #define pm_words 1 int pick_mode=pm_numbers;
class hash_entry { public: hash_entry next; char body; }; typedef hash_entry hash_ptr;
#define hash_table_size 4096 bool hash_initialized=false; int num_hash_entries=0; hash_ptr hash_table[hash_table_size]; int start_word,end_word; char word_list=NULL;
void generate_word_list() { int i,j=0; hash_ptr temph; if (word_list) { free(word_list); } word_list=(char )malloc(sizeof(char )num_hash_entries); for (i=0;i<num_hash_entries;i++) word_list[i]=NULL; for (i=0;i<hash_table_size;i++) { temph=hash_table[i]; while (temph) { word_list[j++]=temph->body; temph=temph->next; } } }
void process_word(char st) { // char src=st; int i; hash_ptr temph,temph1; // while (src) { // src=toupper(src); // src++; // } i=hash_string(st) & (hash_table_size-1); temph=hash_table[i]; while (temph) { if (!strcmp(temph->body,st)) return; temph=temph->next; } temph1=new hash_entry; temph1->body=malloc_string(st); temph1->next=hash_table[i]; hash_table[i]=temph1; num_hash_entries++; }
void process_file(char buf,int len) { int i,j; if (!hash_initialized) { for (i=0;i<hash_table_size;i++) hash_table[i]=NULL; hash_initialized=true; } for (i=0;i<len;) { while (!(buf[i]>='A' && buf[i]<='Z' || buf[i]>='a' && buf[i]<='z' || buf[i]>='0' && buf[i]<='9' || buf[i]=='^' || buf[i]=='=' || buf[i]=='+' || buf[i]=='-' || buf[i]=='/' || buf[i]=='' || buf[i]=='_' || buf[i]=='\'') && i<len) i++; j=i; while (i<len) if (!(buf[i]>='A' && buf[i]<='Z' || buf[i]>='a' && buf[i]<='z' || buf[i]>='0' && buf[i]<='9' || buf[i]=='^' || buf[i]=='=' || buf[i]=='+' || buf[i]=='-' || buf[i]=='/' || buf[i]=='' || buf[i]=='_' || buf[i]=='\'')) { buf[i]=0; break; } else i++; if (j<i) { process_word(buf+j); i++; } } generate_word_list(); }
void CInGodsTimeDlg::OnSelectWords() { int file_size; FILE in_file; char buf,cur_dir[MAX_PATH+32]; CFileDialog d(TRUE,"Txt","",OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, "Text Files (.Txt)|.Txt|All Files (.)|.||");
/* if (m_main.GetLength()) m_main+="\r\n\r\n"; m_main+=d.GetPathName(); m_main+="\r\n\r\n"; / UpdateData(FALSE); }#define DIVISOR 1
void CInGodsTimeDlg::OnStop() { int l,col; LARGE_INTEGER count; // char buf[128];
// sprintf(buf,"\r\n%010u ",count.LowPart/DIVISOR); // m_main+=buf; m_num=(count.LowPart/DIVISOR)% num_hash_entries; m_main+=word_list[m_num]; m_main+=" "; m_num=1; } break; } UpdateData(FALSE); }void CInGodsTimeDlg::OnChoiceWords() { UpdateData(); pick_mode=pm_words; m_num=1; UpdateData(FALSE); }
void CInGodsTimeDlg::OnChoiceNumbers() { UpdateData(); pick_mode=pm_numbers; m_num=1; UpdateData(FALSE); }