Jump to content


  • Posts

  • Joined

  • Last visited

Posts posted by DeX

  1. So you do have an authentication system. Then use it: Make the API reject any request from a client who isn't logged in. And fix the other two vulnerabilities I pointed out.


    A proper API workflow looks like this:

    if not logged_in():
       error("not authorized")
    // validate the input to prevent users from messing with the path 
    if not is_valid_number(quote_id):
       error("invalid ID parameter")
    // delegate file access to webserver (the exact header depends on the webserver software)
    header("X-Accel-Redirect: /path/to/internal/signature/image.png")

    Whether or not your DomPDF manages the resolve the image paths properly is a different story. Google says that remote requests require extra settings in the library.

    Currently I'm doing that, the page sends a request to the controller -> model to create the PDF and this checks for a valid login before proceeding. Then the DOMPDF class is included, the object is initialized and PDF is created / stored on the server. I guess I could flip this around to keep the working PDF code from above where it uses the /var/signatures..... path and creates the quote properly. Then instead I can focus on why displaying the quote on the page breaks the image, maybe that's an easier way of looking at it.


    Why would the page try and load www.domain.com/var/signatures/.....? When I right click the broken image and select the option to load the image in a new tab, this is where it's looking. Why would that be? Can I reference files outside the web directory like this for inline display? Is there a single way to reference it so it works for both?


    EDIT - your comment about extra code needed for external access in DOMPDF, that's setting isRemoteEnabled to true but I believe this is only for referencing files on a separate web server.


    Your current approach doesn't make any sense.


    First off, it seems you don't perform any input validation whatsoever. If that's actually your code, then users can steal arbitrary images (or even arbitrary files) from your server simply by manipulating the file path through the quote parameter:


    I also don't see any concept for user authentication. How do you even know who the current user is and which signatures they own? Keeping the signatures outside of the document root doesn't help when your API script makes them available to everybody again.


    So this needs a major overhaul:

    • Whatever you do, you must validate all input and take extra care when building file paths. You don't want anybody to freely traverse your file system.
    • You need an authentication system (e. g. user accounts protected with passwords).
    • If you insist on this HTML preview, then you need a secure access script which authenticates the user and makes sure they cannot access any files they aren't supposed to access. I strongly recommend you refrain from implementing your own file access code with readfile() and instead delegate the task to the webserver through the “sendfile” mechanism (see the mod_xsendfile module for Apache or X-Accel for nginx). This is much more secure and efficient.


    The only users logged in are approved salesmen, they're the ones creating the quotes and contracts on the system. They effectively have ownership to all signatures so they can create the quotes, it's the public that should not have access to any signatures.


    I'm relying on the fact nobody knows the API location to be able to view signatures, is this incorrect? Should I assign a token to each signature and have the token required to view? I'd much rather just point to the root folder instead, using the API method is not ideal for me, I was just exploring it as an option.


    All users are authenticated with passwords, no pages are visible except the login page without a valid user account. This is all working perfectly already, it's only the API that sends commands through to the controller from outside if I allow them.


    The preview happens when the salesman is creating the quote with the customer, they will sit down together, logged in as the salesman, and they will keep editing options until they achieve the quote price they are happy with. The quote is displayed to the user on the page as they're changing inputs and this is loaded as HTML from the quoteView page. Once the quote is saved, a PDF is created from the HTML code and this PDF generator (DOMPDF) places all the images where they're supposed to go. However when DOMPDF creates the PDF, it's having trouble finding the images using the same path that works with the inline HTML just fine.


    Since the quote is viewed live on screen and also used by the PDF generator, I create it in the quoteView and return it when requested by a logged in user.


    I may be doing something wrong at the very root here but if you'd give me some ways to verify that I would greatly appreciate it. All I know right now is the entire system is working perfectly except I can only choose to load this signature properly inline or on the PDF, not both. Otherwise any other images loaded on the quote work fine, I have the company's logo at the top and that shows on both. That's inside the web directory though.

  3. You're right, I was doing some more testing today and got this far:

                // display
                $imageSource = '/includes/api.php?function=getSignature&quote=' . $_GET['quote'];
                // PDF
                $imageSource = '/var/signatures' . $this->controller->getBranch() . $_GET['quote'] . '.png';

    And my API function does this:

                $mime_type = mime_content_type("/var/signatures" . $controller->getBranch() . $_GET['quote'] . ".png");
                header('Content-Type: '.$mime_type);
                return readfile("/var/signatures" . $controller->getBranch() . $_GET['quote'] . ".png");

    Then it's displayed like so:

    <img width="16" height="16" alt="star" src = "' . $imageSource . '" />

    As you can see I have one imageSource that works with display it and another that works with the PDF generator (DOMPDF). If I use the one that works with the PDF, it doesn't display and that's because it's trying to load the image at www.domain.com/var/signatures/.......

    Why would it do that?


    EDIT - By display, I mean that I'm also trying to display the HTML to the user so they can see the contract. It's the same HTML passed to DOMPDF to create the PDF.

  4. Actually I should keep the images in an outside folder because I have a /var/www/development folder and a /var/www/production folder. I have a script that deploys from development to production when a new version is ready for release and I wouldn't want to copy all of the development testing signatures over the production signatures on a deployment. It would probably be easier if I didn't have the signatures inside that folder at all.

  5. I have a contract and I'm using a signature_pad API I downloaded from Github to allow the user to draw their signature on screen and then it's saved into a folder on my server. When the page reloads, it embeds the signature image into the contract so it appears signed when it's printed out.


    Since I'm saving these signatures onto my server as images, I think it's best if they're not accessible for people to just browse through and download at will so I was saving them to a directory above my web folder so that they're not accessible to the web. The problem now is I can't reference them in any way to have them accessible by the PDF generator when creating a PDF of the quote.


    I could move them into a web accessible folder to solve this but then the public can view them, how do I stop this? Which approach would be best? Thanks.

  6. Right now in my code I have a page that displays a quote (like from a mechanic) and the quote is built in the quoteView. As the quote is displayed on screen, I have some code being called to create a PDF of the quote and save it on the server. So after the call to fetch the quote is made, I call the controller to create the PDF, the controller calls the quoteModel to create it, but the model needs to call the view to build the quote so it can be saved. Should the model call back to the view? Should I just pass in the HTML for the quote from view->controller->model?


    The major issue I have is all views share the same controller so I need to pass that in when creating the view, but the model doesn't have any concept of the controller. I'm still learning this, thanks.

  7. Should I be able to reference any model from any other model? Currently only the controller can access any model it wants information from but once you get into the model, you can't communicate with other models.


    The situation I have right now is a settings page I have where it lists all the items from a table in the database and allows you to modify them or add new ones. So I have a settings model that retrieves all items from that table and the view displays them on the page. I have another model for another page that actually uses these table items and again I need to get all the items from that table in this model. Do I have the same function in both models? Do I move them to a common model that's shared? Do I just choose one and reference them from there?

  8. I have been attempting to implement this for the last little while and am pretty well stuck with it. I am trying to rewrite all product quantity calculations using the multiplier / offset method posted earlier but I just can't get all of them to fall into that format. The white caulking works fine but then I have much more complex quantity calculations.


    A simple one I'm having trouble with is 2x4x16 lumber. These are used end-to-end all the way down both sides of the building. So the quantity calculation is:

    buildingLength / lengthOfBoard (16)

    And then you multiple by 2 for both sides (or loop through again) and then round up. There isn't really a multiplier here since you're dividing, so how would that work?


    A much more complicated example is for 2x8x16 lumber which is like so:

                        for ($i = 0; $i < count(json_decode($this->slidingQuantities, true)); $i++)
                            $quantity += $this->getSlidingDoorWidths($i) * 2 / 16 * $this->getSlidingDoorQuantities($i);

    The salesman can add as many sliding doors to the building as he wants, so he could add 1 set of 2 10x12 doors and then another single 10x10 door to the other side. That's 3 total doors with different dimensions so the code has to loop through each group to calculate the quantity of 2x8x16. Essentially it is:

    - for each group of doors entered

    - individual door width times 2 (to line both sides of the door)

    - divided by 16 which is the length of the board, this will add 1 board every 16 feet because they're end-to-end on both sides of the door

    - multiplied by number of doors in that group because in our example the salesman added 2 doors of identical dimensions in the first group


    This example isn't as easy as a simple multiplier / offset calculation so I'm totally lost how I would allow the user to enter this material into the system and set a quantity calculation for it themselves.


    And if you want to see the ENTIRE quantity calculation for 2x8x16, here it is as we're using it right now. The piece I posted above is only a small part inside this:

                    case (self::lumber2x8x16) :
                        $quantity = 0;
                        if ($this->getPostSize() == 
                            $quantity +=
                                            $this->getBuildingWidth() /
                                            $this->getGablePostSpacing() -
                                        ) *
                                    ) +
                                        $this->getTotalQuantityWindows(true) +
                                    ) *
                                    22 /
                                ) +
                                $this->getTotalOverheadDoorWidths() /
                            for ($i = 0; $i < count(json_decode($this->overheadQuantities, true)); $i++)
                                $quantity += ($this->getBuildingHeight() - $this->getOverheadDoorHeights($i) + 2) * $this->getOverheadDoorWidths($i) * $this->getOverheadDoorQuantities($i) / 4 / 16; // for each door
                        for ($i = 0; $i < count(json_decode($this->slidingQuantities, true)); $i++)
                            $quantity += $this->getSlidingDoorWidths($i) * 2 / 16 * $this->getSlidingDoorQuantities($i);
                        for ($i = 0; $i < count(json_decode($this->biFoldQuantities, true)); $i++)
                            $quantity += $this->getBiFoldDoorWidths($i) / 16 * $this->getBiFoldDoorQuantities($i);
                        if ($this->getEveBoardLength() == 16 || $this->getEveBoardLength() == 15)
                            $count = 0;
                            if ($this->hasSoffit())
                                $quantity += ceil((($this->getLengthGableSoffit() / 12) + ($this->getLengthEveSoffit() / 12)) / $this->getEveBoardLength()) + 1;
                            $quantity += $this->getBuildingLength() * 2 / $this->getEveBoardLength();
                            foreach (json_decode($this->kickWallLengths, true) as $length)
                                if ($this->isKickWallEve($count))
                                    if ($this->getKickWallHeights($count) == 4)
                                        $quantity +=
                                            ceil($this->getKickWallLengths($count) / $this->getEveBoardLength()) *
                                            ($this->isKickWallInsulated($count) ? 7 : 6);
                                    else if ($this->getKickWallHeights($count) == 6)
                                        $quantity +=
                                            ceil($this->getKickWallLengths($count) / $this->getEveBoardLength()) *
                                            ($this->isKickWallInsulated($count) ? 10 : 9);
                                    else if ($this->getKickWallHeights($count) == 
                                        $quantity +=
                                            ceil($this->getKickWallLengths($count) / $this->getEveBoardLength()) *
                                            ($this->isKickWallInsulated($count) ? 13 : 12);
                        if ($this->getGableBoardLength() == 16 || $this->getGableBoardLength() == 15)
                            $count = 0;
                            foreach (json_decode($this->kickWallLengths, true) as $length)
                                if ($this->isKickWallGable($count))
                                    if ($this->getKickWallHeights($count) == 4)
                                        $quantity +=
                                            ceil($this->getKickWallLengths($count) / $this->getGableBoardLength()) *
                                            ($this->isKickWallInsulated($count) ? 7 : 6);
                                    else if ($this->getKickWallHeights($count) == 6)
                                        $quantity +=
                                            ceil($this->getKickWallLengths($count) / $this->getGableBoardLength()) *
                                            ($this->isKickWallInsulated($count) ? 10 : 9);
                                    else if ($this->getKickWallHeights($count) == 
                                        $quantity +=
                                            ceil($this->getKickWallLengths($count) / $this->getGableBoardLength()) *
                                            ($this->isKickWallInsulated($count) ? 13 : 12);
                        if ($this->hasPermaPosts())
                            $quantity += 4 + $this->getTotalQuantityDoors() * 2;
                        $quantities[] = $quantity < 0 ? 0 : ceil($quantity);
  9. I have actually been coding this up for the last 2 months and am now starting on the rules for each product and category in the system. Right now I have a very simple price calculator with categories and products using multipliers and offsets as suggested:


    - final price

    -- lumber x 1 + 0

    --- tenFoot2x4

    -- metal x 1 + 0

    -- labour x 1 + 0


    So the final price is comprised of all lumber, metal and labour combined, and lumber is made up of a single product, a 10' piece of 2x4. I'm assuming for simplicity that this product is only added to the building if the building is insulated, how would I account for this? I have multipliers and offsets but what about conditions such as this? Do I add an additional rule to the product group which has a multiplier of 0 if the user input of "insulated" is false?


    So then it would be:

    - 2x4 quantity = lengthOfBuilding x 1 + 0;

    After applying all these rules for the quantity I then do a group quantity calculation:

    - 2x4 group quantity = 2x4 quantity x insulatedValue + 0;


    ...where insulatedValue is 1 or 0 based on whether the checkbox is checked.

  10. I have a quoting system and the user (administrator level) has the ability to add or remove the inputs it requests of the salesman when doing the quote. There are a few locked inputs which can't be modified but otherwise if the user wants to collect which colour socks the customer has on, they are free to do that by adding an input to require it when doing the quote. Because of this, I'm currently taking all inputs on the page and throwing them into a match table in the database when each quote is saved.


    I'm also taking the locked quote-specific inputs and putting those into corresponding spots in another QUOTE table with just information about the quote. This would include the width / length / height of the structure and the date it was quoted. I would also use the ID of the row from this insert as the quote ID which would be placed on the printed quote as a reference number.


    I'm also taking locked customer-specific data and entering that into a CUSTOMER table and using the auto generated ID of this row as the customer ID.


    The issue I'm having is I'm now duplicating some of the inputs in multiple tables and I'm wondering if I should just keep them all in the match table with all the other inputs and just let the model retrieve them from there when needed. I would then use the same ID for the quote and the customer ID in this case.


    What do you think?

  11. That makes sense, I have implemented it that way now, thanks.

    Should I have separate controllers? Right now I call one controller for everything and it decides which model needs to handle the request. What if I separate them and the quote controller needs data from the user controller?

  12. I'm wondering if I should initialize every view so I can reference any one I want or if I should just have a main view file that I reference and that accesses the correct view file I need.


    The exact scenario I'm dealing with is a situation where I have a number of inputs at the top of the screen and each input has a keyup function which runs a JavaScript function to display the updated quote. It goes as so:

    - JavaScript function (Ajax call)

    - API file receives the Ajax call and requests the quote from the view


    I have multiple view files and one of them is for the quote. Because it's from an Ajax call I can't just include the quote view on the page itself, it needs to be referenced from the API file and so do all of the other views needed by the API.

  13. I have a quoting tool being used by a few companies and would like to turn it into a Software As A Service (SAAS) for the new redesign. I'm wondering what is the best way to go about this so I have some questions:


    1. Should I be using a completely separate database for each new customer? How would I create a new MySQL database and tables in PHP? Just run the full SQL script in one shot after they have paid?


    2. Should I use table prefixes for each customer? I don't think this is a good idea because it bypasses any sort of caching my database would be doing for queries.


    3. Should I use the same database for all and just have a company_id field to state which company the data is for?


    For a little more information, right now I have 2 users and might gain 1 every month or two I'm guessing. Employees would be logging in to create the quotes and customers of that company would be logging in to view their quotes.

  14. You would construct full objects at all times. Only load (objects) what you need for each request.

    If you are going to display a qoute to the user, load all quote data.


    So that makes sense, are you saying I would build a quote object that contains all information I could want about the quote and then just specify what I want from that object in various places on the page? So for instance I would show $quote['id'] in a few places, then show the $quote['price'] where it needs to go and keep using it that way?

  15. I'm ready to start looking into this but I did change something so I'm wondering if I even need to look into anything. We switched it to use port 587 in the client application. Is this sufficient or do I still need to ensure it's actually getting encrypted? And just to make sure I have everything explained, it's using Gmail's SMTP server to send the mail over port 587.

  16. SMTPS on port 465 was deprecated back in the 90s (the port is now reserved for a completely different service). The standard way for mail submission over TLS is to start a plaintext connection on port 587 and then upgrade the protocol with the STARTTLS command. Port 25 is actually reserved for server-to-server communication, but some systems may still accept e-mail submission for legacy reasons.


    In any case, you have to make sure that the connection is in fact encrypted (check both the configuration and the traffic). As I already said, the client has to request the protocol update. If that doesn't happen, everything is plaintext, even when the server does support TLS.


    This seems a little out of my league but I'm going to attempt to break it down.


    1. I'm using the Gmail SMTP server to send the email so is it possible to even send encrypted mail over port 25 with them?


    2. Does the SSL get initiated by the client program initiating the email (our POS) or is the SSL controlled by the email server (Gmail)? I'm basically wondering if this program has the ability to force SSL and Gmail just accepts it, or does the program queue up the email and Gmail decides whether it is encrypted based on the port used?


    3. In order to check if it's encrypted you mentioned checking the configuration and traffic. I'm not quite sure how to check this, can I see the outgoing data somehow?


    4. If I use port 587 will Gmail automatically encrypt it or do I trust our client software will do the encryption? 


    I'm a software guy, not too much of an expert on email servers and transfer protocols. Thanks a lot.

  17. I'm not sure if this is the correct area for this question and it's not really code related but I wasn't sure which forum website was best to ask this.


    One of my clients is doing a huge switch of their entire point of sale (POS) system and they're paying some company in the states a huge amount of money to provide the system and do the switch. We're configuring the desktop application to be able to automatically send out customer invoices or receipts and it needs email credentials in order to authenticate to some SMTP server of our choice.


    I set it up on the dummy Gmail account that I use for all of the printers in the building but for reasons unknown to me this application is for some reason failing to send email over port 465 through the Gmail SMTP server. I've already made all the necessary changes in the Gmail web portal to allow external applications to access email and the printers can access it without issue. However when I switch this application to port 25 it works so I have a few questions regarding this:


    1. Is it safe to continue allowing a POS to send customer receipts over port 25? Can we be sued for breaking some sort of privacy law?


    2. Next to the port setting in the POS application there is a checkbox to use SSL. It allows us to check this, independent of the port selected. Is it possible to use SSL over port 25?

  18. svn ls ^/
    Should show only your branches, tags, and trunk directories.


    Then to make a tag something you copy it to the tags directory under a new name, for example:

    svn cp ^/trunk ^/tags/release-1.0 -m "Release 1.0 tag"
    Branching is the same, but then you copy to the branches directory then switch to the new copy.

    svn cp ^/trunk ^/branches/foo-feature -m "A branch to work on the new foo feature"
    svn switch ^/branches/foo-feature
    To merge a branch back into trunk switch back to trunk and use the merge command.

    svn switch ^/trunk
    svn merge ^/branches/foo-feature .
    # Check for conflicts or any problems.  Once everything is good
    svn commit -m "Merge foo feature"


    Oh man, you're making me very excited to start trying this stuff out. I was going to try and learn how the branching works but now I see it's very simple! I also intend on using the tags for deployment, a previous client has a script for pushing tag versions into production using symlinks so I'm going to attempt to get that working. You really helped me a lot and I appreciate it immensely, thank you.

  19. Use svn move to move the files. Eg:

    svn move addFile.php addUser.php alertmanagement.php ... trunk/
    After the commit just rename your working copy folder to move it out of the way so you can check out a new copy.

    daniel@daniel:~/NetBeansProjects$ mv development.xxxx.com development.xxxx.com-old
    daniel@daniel:~/NetBeansProjects$ svn co svn://development.xxxx.com/trunk development.xxxx.com


    Thanks, I did it! How can we confirm if it worked?

    daniel@daniel:~/NetBeansProjects/development.xxxx.com$ svn info
    Path: .
    Working Copy Root Path: /home/daniel/NetBeansProjects/development.xxxx.com
    URL: svn://development.xxxx.com/trunk
    Relative URL: ^/trunk
    Repository Root: svn://development.xxxx.com
    Repository UUID: 1c66111f-7632-4e47-97ff-b76c4ce8172a
    Revision: 20
    Node Kind: directory
    Schedule: normal
    Last Changed Author: dan
    Last Changed Rev: 20
    Last Changed Date: 2016-12-20 15:39:58 -0700 (Tue, 20 Dec 2016)
  20. In addition to my last post:

    daniel@daniel:~/NetBeansProjects/development.xxxx.com$ svn info svn://development.xxxx.com
    Path: .
    URL: svn://development.xxxx.com
    Relative URL: ^/
    Repository Root: svn://development.xxxx.com
    Repository UUID: 1c66111f-7632-4e47-97ff-b76c4ce8172a
    Revision: 16
    Node Kind: directory
    Last Changed Author: dan
    Last Changed Rev: 16
    Last Changed Date: 2016-12-20 12:53:55 -0700 (Tue, 20 Dec 2016)

    Also I want to be sure I'm moving these files properly. Is this correct?


    1. "svn cp" all local files into the trunk directory (except trunk and tags)

    2. "svn commit" the change

    3. rename my current working copy - how?

    4. check out the files again in the same directory but specify the trunk


    This way the files will still be in the same directory but they'll be checked into / out of the trunk folder on the server.

  21. What's the structure of the files and folders under /usr/local/svn/ like? Post the output of some ls -l commands (or tree if you have it).


    Last login: Mon Dec 19 20:53:34 2016 from 68.145.xxx.xx
    integrity@integrity-server:~$ cd /usr/local/svn
    integrity@integrity-server:/usr/local/svn$ ls -l
    total 8
    -rw------- 1 root root   31 Nov 22 11:22 passwd-team
    drwxrwsr-x 3 root svn  4096 Nov 22 11:20 repositories
    integrity@integrity-server:/usr/local/svn$ cd repositories/
    integrity@integrity-server:/usr/local/svn/repositories$ ls -l
    total 4
    drwxrwsr-x 9 integrity svn 4096 Nov 23 10:42 development.xxxx.com
    integrity@integrity-server:/usr/local/svn/repositories$ cd development.xxxx.com/
    integrity@integrity-server:/usr/local/svn/repositories/development.xxxx.com$ ls -l
    total 36
    drwxrwsr-x 2 integrity svn 4096 Nov 23 10:42 branches
    drwxrwsr-x 2 integrity svn 4096 Nov 22 14:51 conf
    drwxrwsr-x 6 integrity svn 4096 Dec 20 09:51 db
    -r--r--r-- 1 integrity svn    2 Nov 22 11:20 format
    drwxrwsr-x 2 integrity svn 4096 Nov 22 11:20 hooks
    drwxrwsr-x 2 integrity svn 4096 Nov 22 11:20 locks
    -rw-rw-r-- 1 integrity svn  246 Nov 22 11:20 README.txt
    drwxrwsr-x 2 integrity svn 4096 Nov 23 10:42 tags
    drwxrwsr-x 2 integrity svn 4096 Nov 23 10:42 trunk
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.