[ Silence ] >> Alright everybody, welcome to the Walkthrough for our pset7: CS50 Finance. So now, we are beginning our transition from C and just working on the appliance and the terminal and writing C and compiling it into web applications which I think personally are much more exciting. And I've spent a lot of time writing these things. And so you're gonna be actually be able to run something in a web browser and show your friends and they won't have to download the appliance and that'll be awesome. So today's music was Basshunter, another classic. So today, we're going to being going through each part of this problem set. So we're gonna talk a lot about the background of web program in general since we haven't seen a lot of that yet, things like file permissions and what PHP in this mysql are and how you can use them, and then just go through each component of the problem set. So before you start, you wanna set up your appliance to be able to act as a server where a server is something that serves you websites whether they'd be HTML or PHP or whatever you have on inside of your server it's basically going to be able to display them to a user who access these items via URLs and their web browser. So in order to do this, the first thing we need to do is create some folder that's going to be the root of our server. So whenever I go to some URL, the server is gonna jump into this folder and start looking for content at the start of this folder. So this folder just happens to be called public_html and you're going to create that inside of your home directory. So if you say, remember from, you know, week one, this mkdir or make directory, you're going to create a new folder inside of your appliance called public HTML. And all of the web application code you write for this pset, the next pset and your final project is going to live inside of this folder. So after you create it, now that's where you wanna run this git command that's gonna download the distribution code which there's a lot but we're gonna go through it so it's not that scary. Because this is gonna pull down all of the starting code for your pset and make sure that you change directory into public HTML first so you don't pull down all this code inside of your home directory as you're used to. But make sure all of that gets downloaded into public HTML so that way you can access it from the web browser. So after you download anything, we need to change the permissions of everything. Oh, not everything but everything we just downloaded. So we have a new command called "chmod" that we may have seen before. But all chmod does is it's going to change the permissions of either a folder or a file. So if you wanted to make something executable for everyone like your home directory which is something you'll need to do, you're gonna say the word "chmod" so the command to invoke this permission changer, then this a + x. So what does that mean? So this A says I wanna operate on all users, so not just me or not just a certain group, I want everyone and I wanna add the executable permission. So that x for executable means that they can run programs or as we'll soon be doing, run this PHP files that can generate some output. And finally, the last one is just what we're changing. So this [inaudible] says I wanna change my home directory which is located in /home/jharvard. So if we wanted to, as the pset spec does change the permissions to make all of thesethree things executable do your home directory, public HTML, and pset7, all of these things have to be executable. So before you go anywhere, you're gonna need to say "chmod a + x" again, make it executable for everyone all three of these directories. You can specify as many as you want in a list and it's going to change all of those permissions at the same time. So that's for directories but we also wanted to set a different permission for things like images and CSS and HTML files. So if you wanna make sure if something is readable, so not necessarily executable like a binary but just readable like you would open a text file, you'd say chmod again a for everyone, + r this time where the r is gonna say, "I want you to add on the read permission." If you want to do something like subtract the read permission, you'd say "chmod a - r." That's gonna say, "Now, everyone can no longer read it." That's not really something you need to do for this pset. So now if you have a direct [inaudible] /star, that star is gonna say, "Well, everything that's inside of that folder." So the folder itself, you didn't just add the read permission to, you added this read permission to everything inside of the folder where the folder itself could have a different permission than all the files inside of it. So why do we wanna do that? Well, we can't really execute an image as a program, right. We can execute Sudoku and it run. But if we try to run like a jpeg, nothing is really gonna happen unless it's a cool jpeg. So here's a list of this more fine grain permissions. So if I say something like chmod 644 file. So this is gonna change permissions to some file. It's going to set them to 644. So this is unlike the syntax we just saw, we're only adding or subtracting something like the read or the executable permission. What this is doing, if it's going to set individually the permission for the user, some group of users, so every user belong to some group and we don't really care about that. And the last digit is for everyone else. So where do these numbers come from? Well, you'll notice if we have rwx, there are three places for letters. So if we have a letter in every single one of those places, we have kind of like the binary number 111. So that's--what that's going to correspond to is the number 7. So in this 644, this first one is a 6. Where did that 6 come from? Well, I can read so that slot is gonna get a 1. I can write so that slot is gonna get a 1. And in binary, that's gonna be 4 plus 2 which is 6. So I've just said that myself, I can read and write this file called "file." Now for everyone else, I've set a permission of 4. So what does that mean? Well, if we can just jump off to our table and 4 in binary is 100 which means only that R is set. So that means everyone else can just read this file but if I'm jharvard and this file lives inside my home directory, then I can read and write that file because I own it. Does that make sense? Okay. So just a little cheat sheet for you, for the purposes of this pset, every folder you create, you're gonna wanna say chmod 711. Every image HTML, CSS and soon JavaScript, you're gonna chmod 644, and every PHP file you're gonna chmod 600. So that's all you really--that's all--all these really boils down to, and if you forget to set one of these permission things, your website is just not gonna work right. So if at some point you end up at a blank screen, first thing you wanna check is your permissions to make sure that your server can actually read in the files that you're trying to read. So the first part of this assignment is to create your very own home page. So to do that, you wanna create a new file called index.html. You wanna put it inside of this public HTML folder. So if I'm a web browser and I'm going to some URL and it doesn't end in something like test.html but it just ends in some folder name, what the server is gonna do is it's going to look for a file called index. So if I just go to say local host or the IP of the appliance which is 192.168.565.0, I've been working with it too much. If you go to that and you don't say, "Well, I want this files specifically," I just say, "I want whatever is there," what the serve is got to do is it's gonna say, "Okay, I'm looking for something called index." So if I find index.html, I'm going to display that out to the user even though that URL doesn't contain index.html. So once you create it, the first thing you wanna do is make sure you do the chmod 644. So where did that come from? Just from our cheat sheet, HTML, so we're gonna have 644. We don't need to execute it. We just need to read it. So to get that, again, if we're inside the appliance, we can just say, "Local host tilde jharvard." If we're outside of the appliance on our own web browser, we need to have that IP address and then we can view our webpage. So as you make changes to this HTML file, no longer do you have to compile it. As soon as you make a change and you reload the page in your web browser, you're gonna see that change reflecting the page. So no more, you don't have to make HTML files or anything like that. You can just change them and then see your changes. So, one thing that's important for this pset is that the HTML you create inside of your home page has to be a valid HTML. So to do that, it's really, really simple, you can just upload your HTML file to validator.w3c.org, and it's just gonna spell out. Is this valid HTML, yes or no? And if it's not, it's gonna say, "On this line, you have a typo, you need to fix this and then it will be valid." So any questions on that part of the pset? Yup? >> Do we need to be commenting our webpage? >> So do we need to be commenting our webpage? So style counts just as much as it did before inside of web applications as it did for C programs. So maybe inside of your HTML you wanna say, "Like here is where the navigation bar is" like all that file is in navigation bar, here's the footer." You don't really need to say, here's the button, here's the text for the--like you don't need to be that granular. Inside of your PHP though, your actual application logic, you'll probably gonna wanna be as thorough as you were with your C code. But generally with HTML comments, just kind of like where you are in the page roughly, so if I'll just kinda glance at it, I don't need to scroll up and figure out where in the page I'm looking at. I look at the code and the page side by side. I should have a general idea of where things are based on the HTML from the contents--comments. Other questions? Okay. So, no longer are we using the language C but we're now introducing a new language to you called PHP which has one of the best acronyms ever because PH--PHP stands for the PHP hypertext processor. It's one of the best recursive acronyms. So, some major differences between PHP and C, no longer are we writing dot C files, we're now writing dot PHP files. So get out of that habit of saving your files as dot C. So inside of PHP, all of your code is going to be contained within this bracket, question mark and then this PHP is optional. You can omit that if you want if you don't feel like typing it every time. And it's going to close with this question mark bracket. So any PHP code you write must be enclosed between these two characters. You can't just have PHP showing inside of your HTML or else it's not actually going to execute. >> So another perhaps really annoying difference with PHP is all of your variables must start with a dollar sign. There is no way around it, sorry, it gets annoying and you finally have a reason to start typing the 4 on your keyboard. And finally, variables are weekly typed. So when you create a variable, in C we needed to say int A equals something and that something needed to be an integer or you are going to get yelled at. In PHP, we can just say something like dollar sign X equals 5. You don't need to tell PHP that X is an integer because PHP, while it's executing, you can say, "Well, 5 looks like an integer so looks like X is going to be an integer. You don't need to explicitly tell it to that. So simply, when you create a function, you don't need to declare the return type of your function. You can just say, "Here is a function and you figure out what it returns because you're really smart." Questions? Okay. So the major difference between a PHP and C is you no longer have to worry about things like malloc and segfaults and pointers and you'll be so excited when your code no longer segfaults. You just have this like nice little warning messages that tell you exactly where you went wrong. So let's just take a look at some examples of PHP. So I'm going to go inside of my web browser and you'll notice that I'm on my own computer, I'm not inside of my appliance and I've typed in this IP address of my appliance. So 192.168.565.0, that's never going to change whenever you have the appliance running even if it's minimized in the background, you can get at it from that URL. So next to it, I have this tilde jharvard and this says that I'm looking for the public_html folder inside of the jharvard folder. So if I had another user then it will be tilde and then that user's name. But because you always login as jharvard, you're gonna say, "Tilde jharvard," and that's where it's gonna look from public HTML. So inside of public HTML I have a folder. It's called pset7 and within that folder, I have a file, it's called "login.php." So when I type in this URL, the server is gonna say, "Okay, I know exactly what file to give you." It's gonna run the PHP code and display the output." So let's just take a look at what login.php does. So let's open up get it. We're gonna say "file open." So here's my public HTML pset7 and here's login. So, okay, so the first thing it does is it immediately starts a block of PHP code. How do we know that? Because we're starting with this bracket question mark. And until we close it with another bracket, question mark bracket, everything inside of that is going to be PHP. So we're just making a simple function call. So you notice first that this comment in PHP is the same as the comment in C, just slash, slash. And we're saying require_once includes/common.php. So what does that do? Well, that's gonna say, okay, there are some file that exists in the folder includes starting from where this PHP file is right now. And inside of that folder, there are some file called common.php. What I want you to do is basically go in to that file and copy and paste whatever is in there right here. So this is kind of like the define statement we saw on C or the include statement, sorry. We're gonna open some file and just copy and paste whatever is in there right here. So let's take a look at what that looks like. Well, it's open. Okay, here's our folder called includes and then here's common.php. So alright, so this looks like it's doing some kind of complicated stuff. So before we get into that, let's just look at the rest of login.php. So we see some title, so here's the top of my page. And at the top of my page, we have some image. And you'll notice that this image is located inside some folder called images and the image is called logo.gif. So let's just take a look at what that looks like. So if I open up my terminal, I'm gonna go into public_html pset7 images. And if I do an ls, well, there we go. I can see my logo.gif. So if I say ls -l, that -l is gonna tell me to display some additional information. And what's the additional information I've displayed? Well over to the left here you can see the permissions of this file. So if I look at logo.gif, I see that this file is currently set to 644, right. We have 2 bits, which is a 6 and then 2--an r, another r, both of those are 4. So the current permissions of logo.g0ff are 644. And that means that I've--if I'm the web server, I can open up that file and I can display it to you and that's why we can see this logo right there. So now, if I did something like chmod 000 logo.gif and we look at the permissions again, you now notice that they're different. Whoa, if I spell ls right. So you notice that they're different. So now, I've removed all permissions. I've said no one can do anything to this file ever. So now if we jump back to the web browser and we refresh the page, that image is gone because we're no longer allowed to read it. So if you find this happening in your code, first thing you wanna do is try to check permissions. Let's just change it back to 644. Refresh our page again and it's back. So everybody understand how that permissions is gonna work and what things are gonna look like? Okay, so let's a jump back into this login.php. So nothing else suspicious here, we're just displaying those two text fields, that makes sense. There's no more PHP on this page which is good for our understanding. So now let's jump in to common.php. So the first thing we're doing, we're just saying okay PHP, whenever you have some error like you encounter a syntax error or something like that, I want you to be super helpful and I want you to tell me exactly where those errors are. So instead of just core dumped I wanna see, "well, there's an error on line 15 and this is what your error is and this is how you can correct it." So that's just what these two lines say, they just say display all the errors as you possibly can and be super helpful please. So the next of this is just the security measure we're saying, "Well, we just wanna make sure that everything that comes from this cookie, that come from this site are restricted to the URL tilda something/pset7." You do not have to worry about how the hell you parched that, just assume that it works and it does. So now, we're doing this something called "Session Start." So this is creating a new session for the user. So a session is as called a "Super Global." So inside of a session I can store information that's going to persist as I go back and forth through pages. So if you've ever been on CS50.net or any site you login, you notice that when you change pages the site remembers who you are. So if you think about this PHP files look like and if I just create a variable on one PHP file I need to somehow pass that variable to any other PHP file you might rem--you might visit so that I can remember who you are, the easy way to do that is just to put this in some magical variable called "Session." That's going to be accessible through every PHP file on the site that you create. So in order for this session global to work or to be active you need to first just make this function called "Session Start." That says "I'm gonna using session somewhere and I wanna make sure that it works." So now, [inaudible] we're gonna require three more files. So we can just open this up. So the first is called constant.php. Oh, thank God. This is really, really simple. This is just a series of define statements. Just like in C we had that sharp defined, we're just saying everywhere you see DB_NAME, I want you to find and replace that with jharvard_pset7. Of course these credentials probably look familiar to you by now just the user's password is going to be jharvard and crimson. So we're going to use that to get into our database which we'll see later. And so now, we just have a couple other files like helpers. And so this is just gonna contain some handy helper functions. So we can do things like display an error message to the user so we don't have to worry about like displaying an error on a page. If we just say apologize and pass it some string. What this is gonna do is redirect the user to some error page. The error message is going to be whatever you pass in, add this value message. We can also use dump which is really handy if we have some variable or some array or some object. We wanna know what everything inside of that is. If we just call dump, this is gonna redirect you to some other magical page that's just going to contain whatever the variable you pass in this. So this variable can be anything. It could be an array. It can be an object, whatever you want. So log out again, some complicated stuff you don't have to worry about. But you notice that the session destroy they're saying, "Okay, remember that session super global, I want you to wipe it. I wanna make sure that there is nothing there anymore." And so we'll get into the remainder of this file in just a bit. So that's gonna be index.php. So there're a couple of other files you need to worry about, namely these two login files. So we looked at login.php but now let's take a look at login2.php. So let's get rid of these guys and open up login2. So again, the first thing we're doing is requiring this common file. This common file is requiring a bunch of other files but just basically make available to you some helpful constants and functions. So now--Well, so we're creating some new variable username. And notice that I did not give username a type but this is the first time I'm using it. So if I just say dollar sign username I'm now creating a new variable called username. So I'm setting that equal to the result of some function, mysql_real_escape_string, dollar sign underscore POST username. Wow! So what this function does, this mysql_real_escape_string is pretty simple. It's just a security measure. If someone is trying to hack your site and they try to inject some nasty code into--as their username, this function is just gonna get rid of it so your site doesn't get hacked and you look like a [inaudible]. This POST is another super global. So just like session, it's gonna start with the dollar sign underscore and have capital letters. And this POST is going to be the result of whatever the users sent you from some form. >> So where is that form? Well, remember, that we first went to this login.php and that's where we saw that login form. So let's actually take a look at the HTML from that login form. Now what we care about is this form element. So this is what's going to start off the login form, everything that's contained within the form is gonna be a child of this form element. So there are two important attributes. The first of this is Action. You notice that it says login2.php. What this says is it's gonna be whatever form information you entered I wanna send that over to login2.php. So okay, so after the user submits this form they're gonna be redirected to login2.php. So this second parameter is gonna tell me how do I wanna pass the data from this file, login.php, to my other file, which is login2.php. I'm saying method equals POST. Well, that looks kinda familiar because I'm saying dollar underscore POST username. So okay, so that attributes just telling me how to get up the data. So now, let's take a look at this dump function that we saw. So let's say dump this dollar underscore post. So dump is just a function define the helpers.php, I just wanna take a look at what this dollar sign underscore POST thing is. So let's go back to my web browser and I refresh the page, inside of my username is gonna say Tommy, and my password is gonna be something really secret, I'm gonna click login. Okay, so you'll notice that I was sent to as we expected login2.php because that was the action of our forms. So that's where the form sent us. So now inside of this dollar underscore POST variable is going to be this array. So this array has two elements. It has a username, which is Tommy; and it has a password, which is secret. So okay, so this isn't just your regular, old C array. This is now it's called an associative array. Or effectively a hash table, 'cause we have some array that instead of numbers we're now accessing the indices of this array with strings. So PHP has taken care of pset6 for you and made a really nice hash table. And so we can just say, "Well, I want the value stored for the key username." So now username or password where did those come from? They're not just automatic because you called your file login although that would be really sweet. Instead they came from these two input elements. So this input says. "Okay, I want you to create some text field. And whatever the user types into that text field, I want to save it under the key password. So username and password, and because I said that method POST, that means that inside of the super global called POST, I wanna be able to get at whatever the user typed with the key "username." That makes sense? Okay, so now let's just take a look at some other PHP examples before we jump into the database stuff. So I'm gonna create a new file and I'm just gonna save it as test.php. So I'm just saving it inside of my public_html. So I saved it as test.php, the first thing I wanna do--God it's so helpful--is open up these two tags. And these two tags say, right here is gonna be some PHP. So let's do a couple of things. Let's just create a variable so the variable is gonna be 5. Now let's create a function so when the first functions we wrote in C was a function that returns to the sum of two numbers. So you notice I do not need to specify the return type of my function, I'm just going to say "Function." After that, just like we're used to, it's gonna be the name of the function and then the arguments that the function takes. So again these are going to have to start with a dollar sign because the variables and all variables annoyingly start with a dollar sign. So just like we're used to in C, let's just return A plus B. So a whole new language, PHP, but this is pretty simple. It's very, very similar to C. We're taking the concepts we learned with one language and we can just apply them to this one. We know exactly what that means. It says a little difference syntax. So okay, so that means that some--where in this file I have this variable and I have this function. So now let's print out some text. So this H1 tag, this says, "I wanna make this text really, really big." So now we open up this file we can get there, via the URL, jharvard/test.php. So we run that and we just get high, right? Because that makes sense, the code we wrote didn't actually do anything. It didn't does have any output to the user. We just created some variable and create define some function that we haven't used yet. So now let's say that I wanna print out this variable to the user. So let's just say H2 which is just slightly smaller text than H1. So now let's open up another block of PHP. So again bracket and question mark and we're gonna say "print.f, print variable." Make sense? We have some variable it's defined in this file. And even though it's defined at a different block of PHP we can still access it from this other block. So we're gonna say, "Just print out the value of this variable." So let's close the HTML tag so that we're making attempt to be valid, jump back to our web page and run it. And so now, we printed f5. Something you might have noticed is that we didn't actually have to say "printf percent d/n whatever." We can just print out a variable and it doesn't matter what type that variable is because print is smart enough to just print the value itself. So now if we wanted to do something like print the result of some function, how could we do that? So what I wanna write inside of my PHP block here? So let's just say I wanna add up the number 1 and 2 so I can print the sum of 1 and 2. So again, function defined up there but we can access it down here so let's jump over and we printed out 3. So a shortcut that you'll see throughout the pset, instead of typing this print, we can actually just say, "dollar sign equals and then the variable name." So this is equivalent to what we just wrote, this question mark print and then wherever you wanna print. If you just have this equal sign these are equivalent. If you just wanna quickly printout a value. So if we go back to our page and refresh, we notice nothing have--nothing has changed because these two statements are equivalent. So any questions on how are we gonna be using PHP in this pset? Yup? >> So every different function is contained by--if we put in brackets, it's not like in C where you like declare a function inside of something inside of a function then it can't be accessible outside of it, here you can, [inaudible] scope issue? >> Yeah, so this--so the question is how does scoping as you work? So it is a little different than C. And this variable is effectively a global variable as far as this file is concerned anywhere inside this file I can access this variable. So you'll also notice that the blocks of PHP are kind of interspersed with block of non-PHP, right, like this H1 that's says it's high, that's not PHP. So when the server runs this file, it's going to process these blocks in the order that they appear. So if I do something above, I can use that anywhere I want below. But if I declare variable blow here and try to use it up at the top, that's not gonna work. So we can inters--we don't have to have all of our PHP at the top or all at the bottom or something. We can actually intersperse it throughout the page, we can do so between HTML tags to take care of things like formatting and placement other stuff like that. Yup? >> Can you still see the webpage but it can still be invalid code? >> So can I see the webpage if it's invalid code? So let's make it invalid code. Let's just forget that semicolon. So just like in C, this is now a syntax error. So let's see what happens when I open up my webpage. It's like I'm here, we have this really nice message, syntax error expected a function on line 5. So I'm a programmer, I'm gonna go on line 5. Let's say, "Oh, here's a function here." Well, that's kind of unexpected because I'm in the middle of a statement I can't say something like 5 function I need to end this statement before I can create this function so I forgot a semicolon. So if--and you make any syntax errors unfortunately PHP is not smart enough to tell you how to do the pset yet. But things like syntax errors, you're gonna get this nicer message perhaps than you used to seeing for make. Other questions? Yeah? >> How does it know to go to public.html like in your URL bar [inaudible]? >> So how does it know to get to public_html? So this is just a property of the server we're using, which is called Apache. And so when we're using Apache, Apache is gonna say, "Okay, I see this URL and I need to know somewhere on the server which can contain a bunch of other things that aren't necessarily displayed as a website, I need to know where to start looking." And we've just configured the appliance for you that says "I'm gonna start looking in any folder called public_html that's inside a home directory." You can change it if you want, but you certainly don't need to for this or anything else you'll do. So we've just kind of preset up for you to look inside of this public_html. Other questions? Yup? >> Is this webpage accessible if you close the appliance? >> Is this webpage accessible if you close the appliance? It's not. Because in order for something to send us this page it needs--something used to be running that's listening for these requests. So if we shut that down by closing the appliance, we can no longer get up this URL. >> But if we, you know, minimize or something like that, we're still okay. We don't need to have it in the foreground. It just needs to be running somewhere on your computer. Other questions? Alright, so that's a quick walkthrough of the distribution code and we'll see these functions as we go through all the things that you're gonna need to for the purposes of this pset. So again, login2.php or getting the username from that form and restored inside a post. And now what we need to do is look up the user from the database because we can't just allow anyone to login, right. We need to make sure that, A, the user exists, that they typed in the right password before we can actually log them in. So let's take a look at how we do that. So we understand this line, we're just getting from that form on the previous page. We're getting the value the user typed in. So now, we have what's called a SQL query. So this says, "From my database, where a database is just some collection of tables, where tables have columns and rows and that's how you gonna represent all of your values from that database, I wanna look for someone who's username matches the username that I typed in." So were gonna say, "Okay, I wanna get that result. And if there is one person whose username matches because we can't have two people at the username DJM or we're gonna confuse David. So if there's exactly one person and this username exists, then that's when we wanna check what their password is." So now this is where we're comparing passwords. And so this is--so this is a much more secure approach than we've used years previous but what we're saying is, "I'm gonna call this function crypt." And what crypt does is it's going to take your password and encrypt it." So when we create a new user, they're not--we're not storing their actual password in a database. That will really be insecure because if you're like me and had a bunch of people registered for your site in the CS50 fair and they typed in like what the password they used for everything, you now know what their password is. And from our perspective that's really, really insecure because even though that's cool and you can login to their Gmail now you shouldn't actually have the right to know their password. So for security features, for security purposes, we're going to encrypt that. So when we store the password in the database, we're just gonna see some long--what looks like meaningless string of characters that has what we--what we perceive has no relation to their actual password. And so in order to convert this plain text password to this encrypted password, it's gonna be an algorithm that's a little more sophisticated than Visionaire but in order to invoke it, we don't need to know how it works we just need to know that this magical function crypt is going to do it for us. And so now, if we encrypt the password that was typed in and that matches the encrypted password in our database that must mean that the user typed in the right password. Because if they typed in a different password, that's going to hash to something else, which means that these two passwords don't match. Does that make sense? So here, we're effectively comparing what they typed in to what we remembered as their password, but we don't need to know what their password actually is in order to that. So if this is true, if these two hashes match that means the user typed in the right password and at that point we can log them in because we know that those credentials they entered must be valid. So they must actually be the persons they're trying to login as. So what we wanna do is we wanna remember who they are inside of our session. So remember that because we included common.php at the top here and that called that function session_start, that means that were now green light to use this magic session variable. So as we go through our different pages, we're going to store inside it--we're gonna able to use what's inside of this session variable. So this session is basically just an array. Again it's an associative array where instead of using numbers to access buckets, we access those buckets just with strings. So again just to be cache table. So inside of ID, this key ID, we're going to store the user's ID. So every user is gonna have some unique ID and it's probably just gonna be a number the way we've set it up now. So if we take a look at our database, and to do that, I just want to, again, that same IP address and I want to /phpmyadmin. So this is already installed in the appliance for you. If you go to this URL, you can login with jharvard crimson and take a look at the database that we set up for you. So here's what my database looks like. So you'll see that each of these users has unique ID, it's just a number and it's different for everybody. So here's our username and here's our encrypted password. So we don't actually get to see what David's password is, instead we just see this random string of characters that doesn't tell us really anything about his password. So when David logs in, we're comparing this string to the hash of whatever it is that David typed in. So it's this ID that because it's unique to every user, we can use it to identify which user we are. So if we just remember this ID number then we can remember through all of our pages what user is currently logged in and take action accordingly. That makes sense? How we're logging somebody in? Yup? >> Where is the crypt hash function stored? >> So where is the crypt hash function stored? So when we're just logging someone in, we don't actually need to store the value, we'll just need to compare it to what's already there. So if this row hash says the row of my table that I just selected--so if I--my username is Malan then I'm now looking at the row that starts with Malan. And if that has password value is equal to the hash of whatever the user typed in, then we're okay. So when we login, we don't actually store this anywhere. This already must exist in the database, right, because if it didn't, then we couldn't login because that user doesn't exist yet. So in this case, and this is gonna be different when registered users, but for just logging in, we assumed that it already exists so we don't need to store anywhere 'cause we're just reading from the database, we're not writing to it. That makes sense? >> Yeah. >> Other questions? Yup? >> Where is the crypt function included? >> So where is the crypt function included? So just like things like print F and other stuff like that, this is just part of PHP. So this is written for you and it's just automatically included. And PHP has a lot of functions like a lot, like as soon as someone thought a function was a good idea, they just wrote it and duct tape it. So there's probably a function for anything you can possibly think of in PHP, which is fantastic. Other questions? Okay. So that's our logging someone in, to log someone in just means I'm gonna remember who you are and as you visit all these other pages I know you passed my authentication somehow, so you must be the person that I'm remembering right now. So now let's dissect this select query a little bit more. So SQL says for structured query language and it's not really a programming language as much as a way of describing how to retrieve data from a database. So the query we saw before was some select from users where username equals and we use a dollar sign username. So we don't just have to have a constant here, but if we say dollar sign username, then PHP is smart enough to say, "Okay, well, there's some variable username, I wanna use that, instead of the word username." So maybe that's why they decided variables just start the dollar sign. So this first part is gonna be my verb, what am I doing from the database? Well, I'm selecting data. What data do I wanna select? Well, remember the star means everything, so this says, "I wanna get every single column from the row that I'm selecting." So our database can have multiple tables so these from users that says that there's some table called users and I wanna get data from that. So I can have a bunch of tables and each of those tables must have a unique name so we know where to grab data from. Now this "where" is the condition that must be met in order for the row to be returned. So we're saying, "I want every single row where the username is Malan." Now for the user's table that's only gonna be one row. But it can be the case that this be returned more than one row. So if we said, "Well, I wanna get everything from users where either I'm logged in as David or that person has less than 9,000 dollars." So this will return an array of rows not just necessarily 1. So if we don't wanna select every single column, we can actually list out the column names we wanna select. So we can say I wanna select the username in the hash, I don't really care about the ID, this is actually gonna be faster as far as [inaudible] is concerned 'cause we don't need to read every single column. So I just want these two things, again, I've [inaudible] users but this time instead of equal to Malan, I'm saying not equal to Malan. Make sense? And finally, if we don't wanna return the rows in cells but instead want to return how many rows were returned, I can say something like "Select Count." This count is gonna say, "Well, I don't actually want the column data, I just want how many of those--how many of the rows there are." So if we wanted to know inside of CS50 Finance, how many users right now have cash that's greater than 9,000? We could run some query like this. So sites like Facebook who say, you know, we have 750 million users, they probably just--well, not really, but they probably just said like a select count from users that said, well, how many rows are inside of my database? So now I can write Facebook. So that's the SQL. But SQL is not a programming language. PHP is our programing language that's going to utilize SQL. So here are one, two or three, six-step process for using it. So the first thing we need to do is to connect to our database. So this is where those constants come in that we saw on constants.php. We basically need to login to our database from PHP. So this is just another security measure, right. If we have some password in our database that's separate from the password on our server, that means that if our server gets hacked, that means that whoever hacked us might not necessarily have all of our database information which is really good if your database has like credit card numbers which hopefully your final project doesn't. So we're gonna connect to the database with this username and password that we specified and after we connect we're going to select a database. >> So a database can have multiple tables but we can also have multiple databases that contain multiple tables. So the purpose of this pset, you're just working with one single database called pset7. And everything inside the database pset7 has all the tables that you need for this entire pset. So this DB_NAME is just a constant. It's never gonna change for the purposes of this pset. So we're just gonna use pset7. So now we can start running these queries. So we just saw an example of the select queries. So if I say "SELECT star FROM users," that means I'm going to get my entire user's table. I want every column and I have no condition so this is gonna return every row. So it's not gonna actually execute that statement yet because we've just created the string. In order to actually run that query we wanna say my SQL query and then pass in whatever our query was. So because we stored this in a variable called dollar sign query, that's how it knows what query to run. So it's going to return this result object and this result object contains all of the rows that returned by this query. So to iterate through those rows, you can say something like mysql_fetch_array from a result. So this is very similar to using this wild [inaudible] kind of thing. We're gonna have just like inside of our file some cursor inside of our result object. So if I called mysql_fetch_array, the first time I call that, I'm gonna get back the first row that was returned from my query. It's gonna be stored inside of this PHP array row. So from that array I can say something like row zero or row username. And if I call mysql_fetch_array again, it's going to give the next row. So you can kind of see how it can iterate through all the results of our query. We can just say "well, mysql_fetch_array returned something, that means I must have another row to go through and iterate through it--you know, whatever it is that we need to do, print out the values or something like that." So questions on the structure? Yup? >> Do you ever have to say that something is SQL and--but then brackets are not? >>So do we have the same brackets for SQL? We don't actually we can just say that this entire string that you're passing to mysql query that entire thing is just a SQL thing. And so if you have a syntax error in your SQL or that query failed for some reason, then this function mysql_query is gonna return null. So that's a good if you're concerned about error checking in which you are, that's a good thing to check. What do this function actually returned, did it worked, did I have a syntax error, or something like that. Yup? >> You said that mysql_fetch_array [inaudible]? >> Yes, mysql_fetch_array will get one row at a time just like something like fgets would get one line at a time from a string. >> So what kind of index can you use to [inaudible]? >> So what kind of index can you use to kinda jump to a row? So this you can't really just jump to, say, the third row. There's kind of almost no need to do that really just like if you can think of about a problem that would need to jump like the third row to solve, doesn't really exist because you could probably just refine your SQL query to only get that row or something. So the most common thing that we're gonna do is either just get the single row, in much case we're just gonna call it once, or we need to iterate through some set of rows. And to do that, we're just gonna need to put that in to the loop. So because those are the two most common things you're gonna need to do with the mysql result, that's just the way this function was designed. Other questions on using SQL? Okay. So let's jump in to the five parts of this pset. So the first thing we need to do is allow our users to register. So to do that, we're gonna need to create some new page that's equivalent to login.php that displays a form to the user that allows them to choose a username and password. Now we need--from that form we need to pass it to some other file that's gonna do something like make sure our passwords match 'cause we're asking you to say type in the password, confirm your password. So make sure that those are valid, make sure the username doesn't already exist and that if all those [inaudible] check passed, then we actually need to create a new user. So to display a new form, if you like to practice your HTML then you can just start off with the new blank PHP file and start writing but if you're pressed for time like I'm sure you are then you probably just wanna start off with the copying login.php into register.php. And so now we just have this really nice framework we can start operating with because we only need to change a couple of things. The first thing we need to change is going to be this action, so where it send to. So no longer do we wanna send the data to login2.php, because login2 is gonna login the user and we're trying to register a user. Instead, we wanna send it to some file that we can call register2.php. So after we change that attribute, we also need to create a new password field. So just like we saw those input name equals username you just need to create a new one that has a name like password two or confirmed password or something like that. So that when the user enters data into that it gets passed along to this register2.php file. So that's pretty straightforward. Any questions on the HTML part of this? Okay. So now for the server side logic. So the first that you need to do is make sure that nothing is blank, because if the user typed in something blank then we can't allow them to register 'cause that's gonna be an error. So assuming all these things are not blank, we now just need to make sure that the password and the confirmed password match. In this--And at this point, this might be your favorite part of PHP because at long last you can just say if A equals B, and A and B are strings, this will actually work 'cause you no longer have to worry about memory addresses and pointers and whatever that was any way. So the first time you type this you should just be so excited that you can finally do this. So we just need to compare password and password2. If they're the same, we can keep going. If they're not the same, then we can invoke this apologize function that is especially written to display some error message. So we can just say, "apologize your passwords didn't match" or whatever it is that [inaudible] solution says. So questions on that bit? So similarly, we wanna make sure that what they've entered is a valid username. So if you set your database up the way the pset suggests with the unique key on username then SQL is gonna say, "Okay, everything inside of this username column needs to be unique. So if you try to insert something with the same username I'm going to fail. So if the query fails, we know that, well, mysql_query is gonna return null. So in the event that this query fails that might mean that they tried to do--the user tried to insert the same username as something that already existed. So if this query fails for this reason or some other reason, we just wanna apologize again saying there's some error like maybe you typed in a duplicate username. Make sense? Yup? [ Inaudible Remark ] >> Sure. So I was saying here is that mysql_query is gonna return null if you try to insert a non-unique value into a column that you've said this must be unique. My SQL is smart enough to do that for you. If you'd like you could also select it yourself and look for the username, if you don't find it, then insert it. But this unique key is kind of a nice shortcut way of doing that. So now, that we've done all of our error checking, we actually want to add our new user to the table. So we have a new SQL query, a new verb, and now we're going to say "insert." So the insert statement is going to create a new row inside of our database. So insert into the user's table and that user's table I wanna modify these columns. So I wanna give this user a username on some hash which is their password and some cash. So we're starting off with some default value for cash. So those are the columns I wanna modify. What I wanna insert into those columns I wanna say "values," and then this is a list of the values I wanna insert. So this Tommy corresponds to the username. This supersecret password corresponds to the hash of my password. And then finally the cash corresponds to that column. So you notice that because these are--the first two values are strings, I've enclosed them in quotes. But this last value is equivalent of a float or in SQL it's called the decimal, so I don't need to use quotes because it's just a number. So when I actually say "mysql_query" and I add this it's going to go into the database and modify it. So after you visit that PHP file from your browser that makes this call and go back into PHP myadmin and refresh, you're going to have a different table, hopefully, than you did before. Make sense? Alright, so remember that we're using the hash of the password and not the password itself. So we don't just wanna insert password, we wanna insert crypt of the password. So this function crypt, remember, is what's going to return the hash value, we want to insert that, not the password itself because login is looking at the hash. If you do insert the password itself then you're not gonna be able to login even if it's the right password. Make sense? Okay. And so after the user registers, we wanna be able for them to be logged in. And so to log them in, remember, it's really simple. Login the user, just corresponds to changing this session super global. So if we just change that variable that's equivalent to logging the user in. So any questions on registration? Alright, so now we need to worry about these stock quotes. So this stock information is coming from Yahoo Finance. But luckily, we don't really need to worry about how that data is actually being retrieved. So the first thing you need to do again is create some new HTML file that contains a form that's gonna send data to some other file. So following the convention that David setup, we're gonna say "quote. php is gonna display the form and quote2.php is where the data is going to be sent to." So we know how to do that. And our form this time only needs a single row. We're just looking up a single stock symbol. >> So we're just gonna send that data this time to quote2.php. Same thing that we're used to, we know how to do that. So now, one of these functions defined inside of helpers is this function called "lookup." And what this function is going to do for you is hit the Yahoo Finance API, it's gonna ask all the information about whatever stock symbol you pass it. So this data is going to be returned into a stock object. So as far as PHP is concerned, we have things that are a little more powerful than structs called objects. But for this pset, this S thing, the stock thing is really just a struct. So remember a struct just contain multiple members and member to be different types, whatever. So just like in C we have some struct, we wanna get at something inside of it we're gonna use this arrow notation. So the thing--some of the things we were concerned about is the stock symbol, stock name, stock price. So from that variable we just need to display this information. So we see this a little bit earlier but we have a lot of options for displaying data 'cause again PHP is a function for everything. So what we can do is we can say something like prints, price, and then you notice this dot is the string concatenation operator. So if I have a string on the left and a string on the right, this is like saying add those two strings together, combine them into a single string. So if I print out the concatenation of the string price and then whatever value s that price is I'm just gonna get a single string that's displayed out. If you really like typing percent D then printf is still available to you. And finally, if you want to instead of concatenating or create some string that PHP is gonna say, "Okay, I'm gonna jump in to this string and I'm gonna substitute whatever is inside of these brackets for the code that's inside of it." So this code here is actually going to be executed." PHP is gonna say, I want you to look at S price and this is going to effectively return into the string whatever S price was. So this notation is just a little bit cleaner than using the dot but it just says, "Well, everything inside of these two braces just actually run that code and returned that value." Make sense? So questions on actually displaying the stock information or how are we gonna get that information? Alright. Next we're gonna worry about buying stocks. So in order to buy stocks, we need to do a little bit of change in the design of our application. So right now we just have a single table called users. So inside of that user's table, we have a username, a password we have how much money they have. So what we can't really do is have that table keep track of what stocks you own, right. Having another column that's like a comma separated list of stocks is pretty inelegant 'cause we need to keep track of how many stocks they have and that's just kind of lame. So the right way to do this is to create a new table that's dedicated just to portfolios. So inside of that table, we probably wanna keep track of some the ID of the user, we wanna keep track of what stock they bought, so the symbol that corresponds to it or maybe the name of the stock. And finally how many shares that were purchased. So if our first SQL table have those columns, we're gonna create some new tables maybe called portfolio or whatever it is you wanna call it and these are gonna be the columns of that table. So here's just a diagram of what this looks like. So if I'm a user and I buy a new stock then I'm gonna create a new--maybe a new row inside of my portfolio's table. Now the ID of this row can correspond to the ID of the user that purchased the stock. So in this case, this ID is not unique, right. Because as one user I have an ID like seven and if I own like 10 stocks I'm gonna have 10 rows inside of this portfolio's table. So that's how we're kind of connecting these two things. We're associating a row in the portfolio with the user. And the way we do that is just have some column that's gonna be the same value in both of the tables. So then we can just store the symbol as a string and the number of shares that I bought as an integer. Questions on the table structure? Alright. So HTML forms are so fun 'cause we love making them. So now again, we need a symbol, a form that's gonna ask you for what symbol you wanna buy. So if you look at the staff solution which is at cs50.net/finance, I'm gonna login as--yes. So now, if we do something like Get Quote, so Get Quote, and here's our form that's gonna go to quote2, we have this link that say's perhaps you like to buy it. Now if I click buy, you'll notice that this AAPL was pre populated for me, right. In the way that came from was I said well, I wanna quote for apple. And when I said buy, our handy-dandy staff solution was smart enough to recognize that you don't have to type in AAPL again, I'm just gonna type it in for you. So if you look at the URL of this page, you might notice that I'm in the wrong tab--that we're still at buy.php but after that we're saying symbol equals AAPL. So that looks kind of fishy. So let's change the symbol to something like GOOG. You'll notice that I've just by changing the URL I've changed what's inside of this text box. So this is using a different super global this time called "GET." So POST is populated from any form that has a method of POST. So as a corollary to POST we also have this global called GET. So GET is gonna be populated from any form that has a method equal to GET or from the URL. So if you submit a form in which you've said method get, that form is actually going to inside of the URL whatever values you've typed in to the form. So the way it's gonna parsed is by saying, we're gonna have a list of key value pairs. So I'm gonna say key1 is gonna be some value but we're gonna have the ampersand that's gonna separate this key value pairs then I can have another one, and so I can go on and on and on. So if I say get any one of these keys I can get the value that was passed in from the URL. Make sense? So now how did we prepopulate this data? Well, if we go back into our login, so there's an attribute of this input element called value. So if I say value equals Tommy and save this form. So let's go back to the web browser this is my implementation. We're gonna go back to login.php pset7. So now you'll notice that Tommy was prepopulated. Now remember that we don't necessarily have to have all of our PHP at the top of our page. So let's--instead of saying Tommy, let's say something like equals--no, let's say Tommy 'cause [inaudible]. So now, we have some PHP code. So you notice that this is definitely PHP because we have inside of it some bracket question mark and so now we're evaluating this variable. So if I go back into my web browser, this is gonna be the same thing. Well, out of practice, killed me. So it's gonna be the same thing. So we've evaluated this PHP code and we've put it into our HTML. So this construction looks a little weird, right, because we're evaluating PHP in middle of the double quote but that's totally okay. Because as the server is evaluating this PHP file, it's gonna look for everywhere it sees any of these bracket question marks whether they be either HTML or your JavaScript or anywhere, and it's going to evaluate them. So after the server runs this PHP file, it's gonna get some static HTML file where this PHP is going to have been replaced by with whatever it evaluated to. Make sense? Yeah. Alright, so now we need to worry about actually adding the stock that we just bought to our portfolio. So again, don't forget that we're checking, make sure that we're buying, you know, some valid number of stocks, make sure that we're actually buying a stock that exists. So don't forget about all of our checking. So now if have some valid stock, we wanna make sure that the user can afford it. And so that the user affording it means that the amount of cash that they currently have is more than the cost of buying that many shares of stock. So the way we could do that, we can get the amount of cash the user has, we can say, "Well, I wanna select just the cash, I don't really care about my password from the user's table where this ID is equal to whatever the ID of the currently logged in user is." So remember that's just stored in our session. And so we wanna look at session to determine what value we wanna use for our ID in our query. So now what if I'm a user and I buy Apple and I decided, "Well, I wanna buy Apple again." There're a couple of things I can do. So the first is I can say, "Well, if I buy Apple twice then I'm gonna have two rows in my portfolio table that say Apple." And when you display a portfolio you just wanna make sure that you combine those two rows. So inside of my portfolio I don't see Apple twice. I see the sum of all my Apple quotes. Or we can use this other SQL verb called update. So update, unlike insert, is going to only operate on an existing row. So we're gonna say update the user's table and I wanna set the column username equal to n00b wherever, inside of the same row, the username column already has a value Malan. >> So what this says is throw out my table inside of a row, every row that used to have a username of Malan now has a username of n00b. So these two column names don't necessarily have to match. I could change Malan's cash by saying, "Set cash equals 0 where username equals Malan." So after that, that's one way of inserting--of updating the amount of stocks you have. So, the pset mentions it even fancier way that says, "insert" and then "on duplicate key" or something like, "update values." And so that's just a way of invoking this update verb in the event that the stock already exists. So all three of those approaches are totally valid, some a little more straightforward than others. Questions on SQL updates? Yup> [ Inaudible Remark ] >> Yeah. [ Inaudible Remark ] >> So how would you actually type it? So this is going to be a string that we're gonna wanna pass to mysql_query. So inside of our PHP file, we wanna have some string that looks like this, except you wanna substitute into that string probably some--the current username or whatever it is we're changing. So we can substitute the ID to whatever our current logged in ID is or whatever it is we're doing with our query. We don't necessarily have to hard code in those values. So from that string, you just wanna call the function mysql_query on that string and that's how this is gonna gets executed. Other questions? Okay. So finally, we just want to subtract the amount of cash. So if I just bought a bunch of stocks and that price total to a hundred dollars, then we wanna make sure that I now subtract a hundred dollars from the amount of money that that user has. So now unlike--so our cash is not stored in the portfolio table anymore but we're back into the user's table. And so again, we wanna use an update statement. Now, what's cool is we can actually say, "We don't need two separate queries to say, select the amount of cash, get that value, and then update it and use that value." You can actually just say, "Set cash equals cash minus" and then however much the stocks cost. So this is just a handy way of not having to query twice, we can just say "cash." That's gonna be the current value of the cash column for the row in which user name equals Malan. So remember that the price of the stock which we need to calculate the number of shares times the price of one share, that's coming from that lookup function. So before you buy stock, we're gonna call Lookup on the symbol. If we get back a valid stock object, then we can determine how much it cost based on the price attribute of that object. Make sense? So finally, selling stocks is gonna be very similar to buying stocks 'cause again, we just need to operate on a portfolio and then corresponding row in the user's table. So, in order to allow the user to remove stocks, we need to display some list of what stocks they currently own so they can select a stock to delete. So in the staff solution, this is kind of a dropdown menu. And how we got that was we wanna say, "Select star" from portfolio where user name equals Malan. So when you say, "I wanna get every stock that this one user owns." So from those stocks, I can choose to delete all of the stocks that that user owns or sell them. So to remove from the portfolio, we could just say something like--delete, a new SQL verb--"Delete from portfolio where username equals Malan and symbol equals Apple." So now this is saying every Apple stock that Malan has is now deleted. Pretty straightforward, any questions? Alright. So after we've removed the stock from the portfolio, we need to update the amount of cash that that user has. So one thing that I really don't understand about this pset when I did it is that when you sell the stock, it sells for the current price of the stock, not for the price it was when you bought it or else you wouldn't actually ever make any money. So I totally do not understand the stock market when I took this. So when you sell the cash--I mean when you sell stocks, this new cash value is going to come from the current price of the stock which you can get from the lookup function, and just like before, we said "cash minus something" we can just say, "cash equals cash plus something." We just need to give that user back the amount of money that the stock sold for. Make sense? So that's it for selling stocks. And so finally, the pset mentions that we need to keep track of our transaction history. And so, if you look at the staff implementation, you can see the time at which you bought the stock. So if I come over here back to portfolio to history, you can see my entire history and you can see both the date and the time at which I performed each action. So you notice here that I bought 12 shares of A and how much that symbol went for. So I bought 12 shares of A and then I sold and bought some INTC. So if I go back to my portfolio, I only have this A. But the history still needs to keep track. So even if we delete this from the portfolio like it's gone now from that table, the history needs to remember that you had that stock at one point. So one way of doing that is to create another table and call this "Table History." And anytime you do anything whether it'd be buy or sell a stock, that's gonna correspond to a new row inside of that table. So when you sell a stock, you're never deleting any rows. You're gonna create a new row that says, "You sold the stock." So we're never actually losing any information but we have another table that's dedicated to only remembering the information--to only remembering information. Where the portfolio is gonna have rows coming and going as you buy and sell stocks. The history is just going to be a big log, you're only adding rows. So another approach could be, well, I have inside of my portfolio, I'm gonna add another column and that column is either true or false depending upon if I still own that stock. So if I sold all my Apple stocks instead of deleting them, I'm just gonna set all those rows to false. So when I look at my portfolio, I'm gonna get every row that has a value of true, and when I look at my history, I'm gonna get every row that a value of true or false and display bought or sold based on what that column is. So, just two different approaches, there are bunch of other ways you can do this. These are just two ways that make sense to me. And so additionally, in order to keep track of the timestamp at which the action occurred, SQL has a function NOW that's going to return the current time stamp. So if you could say something like insert into history, timestamp, and then just now. You can also set a default value for the column so you can say whenever a new row is inserted, I want this column to have a default value of CURRENT_TIMESTAMP. Then, you don't have to worry at all about actually setting the timestamp yourself. SQL is just gonna say, "Okay, well, because this has a default value of the current time stamp and you didn't tell me what this column should be, I'm just gonna make it the current time." So finally, one more option is PHP's date function which is really, really handy. You can just pass in some generated string of the current date. Any questions on keeping track of history? So finally, just some extra features, you need to pick one of these features and implement it. Allow the users to change their passwords, email receipts of stocks. Every time I buy something I get an email sent to me, deposit additional money so allow the user to increment their cash without selling stocks. And then another one that was just added was allow the user to reset their password. So that last one being kind of difficult because it's an interesting security challenge whereas something like allowing the user change their password, emailing receipts is a little bit on the simpler side. So you're certainly free to implement all of them as long as you implement at least one of them. So any questions on pset7 at all? Yup? So what's the difference between changing your password and resetting your password? >> Sure. So what's the difference between changing your password and resetting your password? So this is a clarification that was literally just made on the spec. But changing your password is for I'm a user and I'm currently logged in and I wanna be able to change my password. Where resetting is like I'm logged out and I forgot what my password is so you need to devise some secure mechanism of allowing user to like click some link and be taken to a page where their password can be reset. So that's definitely the hardest one of these four 'cause it's an interesting challenge. Well, how do I give a user a link that I find someone else and I can't just guess a link and change someone else's password? Other questions? If not, then good luck on pset7. [ Noise ]