答:
Use for-loop, your function will become way simpler and readable, because you will be able to return from the inner loop:

```<code>function findPrimaryNumber(gender, naturalExpressionYearOfBirth) {
  let primaryNumber, primaryNumberGenderObject;

  if (gender === "f") {
    primaryNumberGenderObject = primaryNumberFemales;
  } else if (gender === "m") {
    primaryNumberGenderObject = primaryNumberMales;
  }

  for (let element of primaryNumberGenderObject) {
    for (let yearWeAreLookingFor of element.year) {
      if (yearWeAreLookingFor === naturalExpressionYearOfBirth) {
        return element.number;
      }
    }
  }
}
</code>```

Title: How can I return a value from the main function when using a nested forEach loop without a temporary variable?

Body:
I would like to return primaryNumber without having to use a an extra variable for it.

I would like an arrow statement function that just returns element.number without needing primaryNumber. As it stands the inner forEach is in a different scope so I can't just return element.number from findPrimaryNumber(). Is there a good solution?

function findPrimaryNumber(gender, naturalExpressionYearOfBirth) {
    let primaryNumber, primaryNumberGenderObject;
    if (gender === "f") {
        primaryNumberGenderObject = primaryNumberFemales;
    } else if (gender === "m") {
        primaryNumberGenderObject = primaryNumberMales;
    }

    primaryNumberGenderObject.forEach(element => {
        element.year.forEach(yearWeAreLookingFor => {
            if (yearWeAreLookingFor === naturalExpressionYearOfBirth) {
                primaryNumber = element.number;
            }
        });
    });
    return primaryNumber;
}

Here is an example of the object it is searching:

const primaryNumberMales = [{
    name: "Fire Yin",
    number: 9,
    year: [1910,
      1919,
      1928,
      1937,
      1946,
      1955,
      1964,
      1973,
      1982,
      1991,
      2000,
      2009,
      2018
    ]
  },
  {
    name: "Mountain Yang",
    number: 8,
    year: [1911,
      1920,
      1929,
      1938,
      1947,
      1956,
      1965,
      1974,
      1983,
      1992,
      2001,
      2010,
      2019,
    ]
  },
  {
    name: "Lake Yin",
    number: 7,
    year: [1912,
      1921,
      1930,
      1939,
      1948,
      1957,
      1966,
      1975,
      1984,
      1993,
      2002,
      2011,
      2020,
    ]
  },
  {
    name: "Sky Yang",
    number: 6,
    year: [1913,
      1922,
      1931,
      1940,
      1949,
      1958,
      1967,
      1976,
      1985,
      1994,
      2003,
      2012,
      2021,
    ]
  },
  {
    name: "Earth Core Yang",
    number: 5,
    year: [1914,
      1923,
      1932,
      1941,
      1950,
      1959,
      1968,
      1977,
      1986,
      1995,
      2004,
      2013,
      2022,
    ]
  },
  {
    name: "Wind Yin",
    number: 4,
    year: [1915,
      1924,
      1933,
      1942,
      1951,
      1960,
      1969,
      1978,
      1987,
      1996,
      2005,
      2014,
      2023,
    ]
  },
  {
    name: "Thunder Yang",
    number: 3,
    year: [1916,
      1925,
      1934,
      1943,
      1952,
      1961,
      1970,
      1979,
      1988,
      1997,
      2006,
      2015,
      2024,
    ]
  },
  {
    name: "Earth Yin",
    number: 2,
    year: [1917,
      1926,
      1935,
      1944,
      1953,
      1962,
      1971,
      1980,
      1989,
      1998,
      2007,
      2016,
      2025,
    ]
  },
  {
    name: "Sea Yang",
    number: 1,
    year: [1918,
      1927,
      1936,
      1945,
      1954,
      1963,
      1972,
      1981,
      1990,
      1999,
      2008,
      2017,
      2026,
    ]
  }
];

Body:
Use for-loop, your function will become way simpler and readable, because you will be able to return from the inner loop:

function findPrimaryNumber(gender, naturalExpressionYearOfBirth) {
  let primaryNumber, primaryNumberGenderObject;

  if (gender === "f") {
    primaryNumberGenderObject = primaryNumberFemales;
  } else if (gender === "m") {
    primaryNumberGenderObject = primaryNumberMales;
  }

  for (let element of primaryNumberGenderObject) {
    for (let yearWeAreLookingFor of element.year) {
      if (yearWeAreLookingFor === naturalExpressionYearOfBirth) {
        return element.number;
      }
    }
  }
}


来源: stackexchange

问:
How can I merge overlapping strings in python?
I have some strings,

```<code>['SGALWDV', 'GALWDVP', 'ALWDVPS', 'LWDVPSP', 'WDVPSPV']
</code>```

These strings partially overlap each other. If you manually overlapped them you would get:

```<code>SGALWDVPSPV
</code>```

I want a way to go from the list of overlapping strings to the final compressed string in python.  I feel like this must be a problem that someone has solved already and am trying to avoid reinventing the wheel.  The methods I can imagine now are either brute force or involve getting more complicated by using biopython and sequence aligners than I would like.  I have some simple short strings and just want to properly merge them in a simple way.

Does anyone have any advice on a nice way to do this in python?  Thanks!

答:
Here's my solution which borders on brute force from the OP's perspective.  It's not bothered by order (threw in a random shuffle to confirm that) and there can be non-matching elements in the list, as well as other independent matches.  Assumes overlap means not a proper subset but independent strings with elements in common at the start and end:

```<code>from collections import defaultdict
from random import choice, shuffle

def overlap(a, b):
    """ get the maximum overlap of a & b plus where the overlap starts """

    overlaps = []

    for i in range(len(b)):
        for j in range(len(a)):
            if a.endswith(b[:i + 1], j):
                overlaps.append((i, j))

    return max(overlaps) if overlaps else (0, -1)

lst = ['SGALWDV', 'GALWDVP', 'ALWDVPS', 'LWDVPSP', 'WDVPSPV', 'NONSEQUITUR']

shuffle(lst)  # to verify order doesn't matter

overlaps = defaultdict(list)

while len(lst) > 1:
    overlaps.clear()

    for a in lst:
        for b in lst:
            if a == b:
                continue

            amount, start = overlap(a, b)
            overlaps[amount].append((start, a, b))

    maximum = max(overlaps)

    if maximum == 0:
        break

    start, a, b = choice(overlaps[maximum])  # pick one among equals

    lst.remove(a)
    lst.remove(b)
    lst.append(a[:start] + b)

print(*lst)
</code>```

OUTPUT

```<code>% python3 test.py
NONSEQUITUR SGALWDVPSPV
%
</code>```

Computes all the overlaps and combines the largest overlap into a single element, replacing the original two, and starts process over again until we're down to a single element or no overlaps.

The overlap() function is horribly inefficient and likely can be improved but that doesn't matter if this isn't the type of matching the OP desires.

ContentLicense: CC BY-SA 3.0

Body:
I have some strings,

['SGALWDV', 'GALWDVP', 'ALWDVPS', 'LWDVPSP', 'WDVPSPV']

These strings partially overlap each other. If you manually overlapped them you would get:

SGALWDVPSPV

I want a way to go from the list of overlapping strings to the final compressed string in python.  I feel like this must be a problem that someone has solved already and am trying to avoid reinventing the wheel.  The methods I can imagine now are either brute force or involve getting more complicated by using biopython and sequence aligners than I would like.  I have some simple short strings and just want to properly merge them in a simple way.

Does anyone have any advice on a nice way to do this in python?  Thanks!

Body:
Here's my solution which borders on brute force from the OP's perspective.  It's not bothered by order (threw in a random shuffle to confirm that) and there can be non-matching elements in the list, as well as other independent matches.  Assumes overlap means not a proper subset but independent strings with elements in common at the start and end:

from collections import defaultdict
from random import choice, shuffle

def overlap(a, b):
    """ get the maximum overlap of a & b plus where the overlap starts """

    overlaps = []

    for i in range(len(b)):
        for j in range(len(a)):
            if a.endswith(b[:i + 1], j):
                overlaps.append((i, j))

    return max(overlaps) if overlaps else (0, -1)

lst = ['SGALWDV', 'GALWDVP', 'ALWDVPS', 'LWDVPSP', 'WDVPSPV', 'NONSEQUITUR']

shuffle(lst)  # to verify order doesn't matter

overlaps = defaultdict(list)

while len(lst) > 1:
    overlaps.clear()

    for a in lst:
        for b in lst:
            if a == b:
                continue

            amount, start = overlap(a, b)
            overlaps[amount].append((start, a, b))

    maximum = max(overlaps)

    if maximum == 0:
        break

    start, a, b = choice(overlaps[maximum])  # pick one among equals

    lst.remove(a)
    lst.remove(b)
    lst.append(a[:start] + b)

print(*lst)

OUTPUT

% python3 test.py
NONSEQUITUR SGALWDVPSPV
%

Computes all the overlaps and combines the largest overlap into a single element, replacing the original two, and starts process over again until we're down to a single element or no overlaps.

The overlap() function is horribly inefficient and likely can be improved but that doesn't matter if this isn't the type of matching the OP desires.


问:
visual studio: How to ignore pdb not loaded warnings during debug?
While debugging, I do not want visual studio to be looking for *.pdb files from 3rd party *.dlls. For example I use Jetbrains Resharper TaskRunner for unit testing. To use it requires a reference to Jetbrains.Resharper.TaskRunnerFramework.dll. When I debug my application via the TaskRunner, I end up with something similar to this picture below:

Well, I'm not debugging the task runner. That isn't my code anyhow. I want Visual Studio to be "smart" enough (or have a setting) to automatically know to NOT concern itself with *.pdb files for anything that isn't my code. Is this possible?

答:
Add a .gitignore file to your solution and add all extensions you want to ignore
Add this in your .gitignore file *.pdb</p>


问:
Qt program to read text sees only one line in multi-line file
I wrote a program to read a sequence of integer scores one per line in a text file. The file has a header which needs to be skipped.
Despite staring at this program, it only sees the first line (the header) and then behaves as if it's at the end.

```<code>#include <QCoreApplication>
#include <QString>
#include <QTextStream>
#include <QDebug>
#include <QFile>

bool readScores(QString path)
{
  int line_count = 0;
  QFile qFile(path);
  if(!qFile.exists())
    {
      qDebug()<<"path does not exist:" << path;
      return false;
    }
  if(!qFile.open(QIODevice::ReadOnly|QIODevice::Text)){
      qDebug("open fails");
      return false;
    }
  QTextStream ts(&qFile);
  qDebug()<<ts.readLine();// just read the head...
  while(!qFile.atEnd())
    {
      line_count++;
      int score;
      QTextStream tsLine;
      QString line = ts.readLine(512);
      tsLine.setString(&line);
      tsLine >> score;
      qDebug()<<"Just read"<<score;
    }
  qDebug()<<"found "<<line_count<<" lines";
  qFile.close();
  return true;
}

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  readScores("e:/tmp/scores.txt");
  return a.exec();
}
</code>```

And here is the content of scores.txt:

```<code>just test data
69
48
38
2
5
1
1
4
</code>```

Here is the program's output

```<code>"just test data"
found  0  lines
</code>```

Can you see why the program does not see the 8 lines of scores?
I'm using Qt 5.3.1 on Windows with Mingw32

答:
When you use QTextStream you should no longer use QFile:</p>

```<code>bool readScores(QString path)
{
    [...]
    QTextStream ts(&qFile);
    qDebug()<<ts.readLine();// just read the head...
    QString line;
    do
    {
        line = ts.readLine();
        bool ok;
        int score = line.toInt(&ok);
        if(ok){
            qDebug()<<"Just read"<<score;
            line_count++;
        }
    }
    while (!line.isNull());
    qDebug()<<"found "<<line_count<<" lines";
    qFile.close();
    return true;
}
</code>```

Body:
I wrote a program to read a sequence of integer scores one per line in a text file. The file has a header which needs to be skipped.
Despite staring at this program, it only sees the first line (the header) and then behaves as if it's at the end.

#include <QCoreApplication>
#include <QString>
#include <QTextStream>
#include <QDebug>
#include <QFile>

bool readScores(QString path)
{
  int line_count = 0;
  QFile qFile(path);
  if(!qFile.exists())
    {
      qDebug()<<"path does not exist:" << path;
      return false;
    }
  if(!qFile.open(QIODevice::ReadOnly|QIODevice::Text)){
      qDebug("open fails");
      return false;
    }
  QTextStream ts(&qFile);
  qDebug()<<ts.readLine();// just read the head...
  while(!qFile.atEnd())
    {
      line_count++;
      int score;
      QTextStream tsLine;
      QString line = ts.readLine(512);
      tsLine.setString(&line);
      tsLine >> score;
      qDebug()<<"Just read"<<score;
    }
  qDebug()<<"found "<<line_count<<" lines";
  qFile.close();
  return true;
}

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  readScores("e:/tmp/scores.txt");
  return a.exec();
}

And here is the content of scores.txt:

just test data
69
48
38
2
5
1
1
4

Here is the program's output

"just test data"
found  0  lines

Can you see why the program does not see the 8 lines of scores?
I'm using Qt 5.3.1 on Windows with Mingw32

Body:
When you use QTextStream you should no longer use QFile:

bool readScores(QString path)
{
    [...]
    QTextStream ts(&qFile);
    qDebug()<<ts.readLine();// just read the head...
    QString line;
    do
    {
        line = ts.readLine();
        bool ok;
        int score = line.toInt(&ok);
        if(ok){
            qDebug()<<"Just read"<<score;
            line_count++;
        }
    }
    while (!line.isNull());
    qDebug()<<"found "<<line_count<<" lines";
    qFile.close();
    return true;
}


问:
Display places 2 weeks or older with Ruby on Rails + PostgresQL
This topic has been covered before, but I am new and trying to understand. My app is designed to store the locations of an item and since time matters, I wanted to create a link for a view that would ONLY show places that are two weeks or older. I understand I should create a method in the model similar to what's below, but I am just confused on this code. I have been trying to find material to read to understand better. The homepage shows all the places, but I want a link to also show 2 weeks or older.

Along with help, I would love any good reads to help me understand better. Thanks so much SO!

```<code>def self.recent_places
  Place.select("p.*, COUNT(v.id) AS count").where("post.created_at >= 2.week.ago.utc")
end
</code>```

This is a link to the GitHub.
https://github.com/Mbartlett413/DumpStack

答:
I actually just solved this for my own app, this is the method that I used inside my model:</p>

```<code>scope :recent_places, -> {
  where(Place.arel_table[:created_at].lt(2.weeks.ago))
}
</code>```

Body:
This topic has been covered before, but I am new and trying to understand. My app is designed to store the locations of an item and since time matters, I wanted to create a link for a view that would ONLY show places that are two weeks or older. I understand I should create a method in the model similar to what's below, but I am just confused on this code. I have been trying to find material to read to understand better. The homepage shows all the places, but I want a link to also show 2 weeks or older.

Along with help, I would love any good reads to help me understand better. Thanks so much SO!

def self.recent_places
  Place.select("p.*, COUNT(v.id) AS count").where("post.created_at >= 2.week.ago.utc")
end

This is a link to the GitHub.
https://github.com/Mbartlett413/DumpStack

Body:
I actually just solved this for my own app, this is the method that I used inside my model:

scope :recent_places, -> {
  where(Place.arel_table[:created_at].lt(2.weeks.ago))
}


问:
Exploit a backup program using C
I'm doing an assignment of a security course that asks me to find 4 vulnerabilities of a backup program (setuid) and use each of them to gain root access (on a virtual linux machine with old version of gcc etc.).
There should be one of buffer overflow and one of format string.

Could anyone help me to point out where the 4 vulnerabilities are?
I think the buffer overflow can happened in copyFile().

The following is the code for backup.c: (which can be invoked in "backup backup foo" or "backup restore foo")

```<code>#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#define CMD_BACKUP 0
#define CMD_RESTORE 1

#define BACKUP_DIRECTORY "/usr/share/backup"
#define FORBIDDEN_DIRECTORY "/etc"

static
int copyFile(char* src, char* dst)
{
  char buffer[3072]; /* 3K ought to be enough for anyone*/
  unsigned int i, len;
  FILE *source, *dest;
  int c;

  source = fopen(src, "r");
  if (source == NULL) {
    fprintf(stderr, "Failed to open source file\n");
    return -1;
  }

  i = 0;
  c = fgetc(source);
  while (c != EOF) {
    buffer[i]  = (unsigned char) c;
    c = fgetc(source);
    i++;
  }

  len = i;
  fclose(source);

  dest = fopen(dst, "w");
  if (dest == NULL) {
    fprintf(stderr, "Failed to open destination file\n");
    return -1;
  }

  for(i = 0; i < len; i++)
    fputc(buffer[i], dest);

  fclose(dest);

  return 0;
}

static
int restorePermissions(char* target)
{
  pid_t pid;
  int status;
  char *user, *userid, *ptr;
  FILE *file;
  char buffer[64];
  mode_t mode;

  // execute "chown" to assign file ownership to user
  pid = fork();

  // error
  if (pid < 0) {
    fprintf(stderr, "Fork failed\n");
    return -1;
  }

  // parent
  if (pid > 0) {
    waitpid(pid, &status, 0);
    if (WIFEXITED(status) == 0 || WEXITSTATUS(status) < 0)
      return -1;
  }
  else {

    // child
    // retrieve username
    user = getenv("USER");
    // retrieve corresponding userid
    file = fopen("/etc/passwd", "r");
    if (file == NULL) {
      fprintf(stderr, "Failed to open password file\n");
      return -1;
    }
    userid = NULL;
    while (!feof(file)) {
      if (fgets(buffer, sizeof(buffer), file) != NULL) {
    ptr = strtok(buffer, ":");
    if (strcmp(ptr, user) == 0) {
      strtok(NULL, ":"); // password
      userid = strtok(NULL, ":"); // userid
      ptr = strtok(NULL, ":"); // group
      *ptr = '\0';
      break;
    }
      }
    }

    if (userid != NULL)
      execlp("/bin/chown", "/bin/chown", userid, target, NULL);

    // reached only in case of error
    return -1;
  }

  mode = S_IRUSR | S_IWUSR | S_IEXEC;
  chmod(target, mode);

  return 0;
}

static
void usage(char* parameter)
{
  char newline = '\n';
  char output[96];
  char buffer[96];

  snprintf(buffer, sizeof(buffer),
        "Usage: %.60s backup|restore pathname%c", parameter, newline);

  sprintf(output, buffer);
  printf(output);
}

int main(int argc, char* argv[])
{
  int cmd;
  char *path, *ptr;
  char *forbidden = FORBIDDEN_DIRECTORY;
  char *src, *dst, *buffer;
  struct stat buf;

  if (argc != 3) {
    usage(argv[0]);
    return 1;
  }

  if (strcmp("backup", argv[1]) == 0) {
    cmd = CMD_BACKUP;
  }
  else if (strcmp("restore", argv[1]) == 0) {
    cmd = CMD_RESTORE;
  } else {
    usage(argv[0]);
    return 1;
  }

  path = argv[2];

  // prevent access to forbidden directory
  ptr = realpath(path, NULL);
  if (ptr != NULL && strstr(ptr, forbidden) == ptr) {
    fprintf(stderr, "Not allowed to access target/source %s\n", path);
    return 1;
  }

  // set up paths for copy operation
  buffer = malloc(strlen(BACKUP_DIRECTORY) + 1 + strlen(path) + 1);
  if (buffer == NULL) {
    fprintf(stderr, "Failed to allocate memory\n");
    return 1;
  }

  if (cmd == CMD_BACKUP) {
    src = path;

    dst = buffer;
    strcpy(dst, BACKUP_DIRECTORY);
    strcat(dst, "/");
    strcat(dst, path);
  }
  else {
    src = buffer;
    strcpy(src, BACKUP_DIRECTORY);
    strcat(src, "/");
    strcat(src, path);

    dst = path;

    // don't overwrite existing file if we don't own it
    if (stat(dst, &buf) == 0 && buf.st_uid != getuid()) {
      fprintf(stderr, "Not your file: %s\n", dst);
      return 1;
    }
  }

  // perform actual backup/restore operation
  if (copyFile(src, dst) < 0)
    return 1;

  // grant user access to restored file
  if (cmd == CMD_RESTORE) {
    if (restorePermissions(path) < 0)
      return 1;
  }

  return 0;
}
</code>```

And something useful:

```<code>  // one way to invoke backup
  //system("/usr/local/bin/backup backup foo");

  // another way
  args[0] = TARGET; args[1] = "backup";
  args[2] = "foo"; args[3] = NULL;

  env[0] = NULL;
  if (execve(TARGET, args, env) < 0)
    fprintf(stderr, "execve failed.\n");
  exit(0);
</code>```

答:
The format vulnerability is in usage() - with the sprintf() and printf() taking format strings that are generated from argv[0], which an attacker can manipulate to contain whatever they want.

The main buffer overflow is the one highlighted by Péter Török; when scanning code for security vulnerabilities, any unchecked buffer filling with blatant comments like that is a signpost asking for trouble.

The environment variable USER is used - it could be manipulated by the unscrupulous, but it is debatable whether it would really buy you anything.  You could set it to say 'root', and the attempted 'chown' command would user the name it was told to use.

There's a race of sorts between the chown command and the chmod() system call.  It isn't immediately clear how you'd exploit that separately from the other issues - but it might give you something to leverage.

Including <sys/types.h> twice is redundant but otherwise harmless.  With POSIX 2008, it isn't even needed in most places at all.

Title: Exploit a backup program using C

Body:
I'm doing an assignment of a security course that asks me to find 4 vulnerabilities of a backup program (setuid) and use each of them to gain root access (on a virtual linux machine with old version of gcc etc.).
There should be one of buffer overflow and one of format string.

Could anyone help me to point out where the 4 vulnerabilities are?
I think the buffer overflow can happened in copyFile().

The following is the code for backup.c: (which can be invoked in "backup backup foo" or "backup restore foo")

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#define CMD_BACKUP 0
#define CMD_RESTORE 1

#define BACKUP_DIRECTORY "/usr/share/backup"
#define FORBIDDEN_DIRECTORY "/etc"

static
int copyFile(char* src, char* dst)
{
  char buffer[3072]; /* 3K ought to be enough for anyone*/
  unsigned int i, len;
  FILE *source, *dest;
  int c;

  source = fopen(src, "r");
  if (source == NULL) {
    fprintf(stderr, "Failed to open source file\n");
    return -1;
  }

  i = 0;
  c = fgetc(source);
  while (c != EOF) {
    buffer[i]  = (unsigned char) c;
    c = fgetc(source);
    i++;
  }

  len = i;
  fclose(source);

  dest = fopen(dst, "w");
  if (dest == NULL) {
    fprintf(stderr, "Failed to open destination file\n");
    return -1;
  }

  for(i = 0; i < len; i++)
    fputc(buffer[i], dest);

  fclose(dest);

  return 0;
}

static
int restorePermissions(char* target)
{
  pid_t pid;
  int status;
  char *user, *userid, *ptr;
  FILE *file;
  char buffer[64];
  mode_t mode;

  // execute "chown" to assign file ownership to user
  pid = fork();

  // error
  if (pid < 0) {
    fprintf(stderr, "Fork failed\n");
    return -1;
  }

  // parent
  if (pid > 0) {
    waitpid(pid, &status, 0);
    if (WIFEXITED(status) == 0 || WEXITSTATUS(status) < 0)
      return -1;
  }
  else {

    // child
    // retrieve username
    user = getenv("USER");
    // retrieve corresponding userid
    file = fopen("/etc/passwd", "r");
    if (file == NULL) {
      fprintf(stderr, "Failed to open password file\n");
      return -1;
    }
    userid = NULL;
    while (!feof(file)) {
      if (fgets(buffer, sizeof(buffer), file) != NULL) {
    ptr = strtok(buffer, ":");
    if (strcmp(ptr, user) == 0) {
      strtok(NULL, ":"); // password
      userid = strtok(NULL, ":"); // userid
      ptr = strtok(NULL, ":"); // group
      *ptr = '\0';
      break;
    }
      }
    }

    if (userid != NULL)
      execlp("/bin/chown", "/bin/chown", userid, target, NULL);

    // reached only in case of error
    return -1;
  }

  mode = S_IRUSR | S_IWUSR | S_IEXEC;
  chmod(target, mode);

  return 0;
}

static
void usage(char* parameter)
{
  char newline = '\n';
  char output[96];
  char buffer[96];

  snprintf(buffer, sizeof(buffer),
        "Usage: %.60s backup|restore pathname%c", parameter, newline);

  sprintf(output, buffer);
  printf(output);
}

int main(int argc, char* argv[])
{
  int cmd;
  char *path, *ptr;
  char *forbidden = FORBIDDEN_DIRECTORY;
  char *src, *dst, *buffer;
  struct stat buf;

  if (argc != 3) {
    usage(argv[0]);
    return 1;
  }

  if (strcmp("backup", argv[1]) == 0) {
    cmd = CMD_BACKUP;
  }
  else if (strcmp("restore", argv[1]) == 0) {
    cmd = CMD_RESTORE;
  } else {
    usage(argv[0]);
    return 1;
  }

  path = argv[2];

  // prevent access to forbidden directory
  ptr = realpath(path, NULL);
  if (ptr != NULL && strstr(ptr, forbidden) == ptr) {
    fprintf(stderr, "Not allowed to access target/source %s\n", path);
    return 1;
  }

  // set up paths for copy operation
  buffer = malloc(strlen(BACKUP_DIRECTORY) + 1 + strlen(path) + 1);
  if (buffer == NULL) {
    fprintf(stderr, "Failed to allocate memory\n");
    return 1;
  }

  if (cmd == CMD_BACKUP) {
    src = path;

    dst = buffer;
    strcpy(dst, BACKUP_DIRECTORY);
    strcat(dst, "/");
    strcat(dst, path);
  }
  else {
    src = buffer;
    strcpy(src, BACKUP_DIRECTORY);
    strcat(src, "/");
    strcat(src, path);

    dst = path;

    // don't overwrite existing file if we don't own it
    if (stat(dst, &buf) == 0 && buf.st_uid != getuid()) {
      fprintf(stderr, "Not your file: %s\n", dst);
      return 1;
    }
  }

  // perform actual backup/restore operation
  if (copyFile(src, dst) < 0)
    return 1;

  // grant user access to restored file
  if (cmd == CMD_RESTORE) {
    if (restorePermissions(path) < 0)
      return 1;
  }

  return 0;
}

And something useful:

  // one way to invoke backup
  //system("/usr/local/bin/backup backup foo");

  // another way
  args[0] = TARGET; args[1] = "backup";
  args[2] = "foo"; args[3] = NULL;

  env[0] = NULL;
  if (execve(TARGET, args, env) < 0)
    fprintf(stderr, "execve failed.\n");
  exit(0);

ContentLicense: CC BY-SA 2.5


问:
DjangoREST json parsing id instead of name
im new to Django (and to the DjangoREST framework)and and I've been struggling for a while with the following:

I want for "especies" (apologies for the portuguese..) to be a vector with the names of the model Especies(scroll down pls) and instead this is giving me the id corresponding to the Especie.

```<code>"especies": [
            13,
            14
        ]
</code>```

I want, for example:

```<code>"especies": [
            Z1,
            Z2
        ]
</code>```

Thanks in advance!

The JSON parsed:

```<code>    {
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
        "codigo": "Z3",
        "area": "Z_tres",
        "especies": [
            13,
            14
        ],
        "id": 17
    }
    ]
}
</code>```

FROM THE DJANGO REST APP:

views.py

```<code>from django.shortcuts import render
from species.models import Especie, Zona, EspecieZona
from rest_framework import viewsets
from rest.serializers import ZonaSerializer

class ZonaViewSet(viewsets.ModelViewSet):
    queryset = Zona.objects.all()
    serializer_class = ZonaSerializer
</code>```

serializers.py

```<code>from species.models import Zona
from rest_framework import serializers

class ZonaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Zona
        fields = ('codigo', 'area', 'especies', 'id')
</code>```

The models.py on this app is empty.

FROM THE MAIN APP

models.py

```<code>from django.db import models

class Zona(models.Model):
    codigo          = models.CharField(max_length=120)
    area            = models.CharField(max_length=120)
    especies        = models.ManyToManyField("Especie", blank=True)
    def __str__(self):
        return self.codigo

class Especie(models.Model):
    nome            = models.CharField(max_length=120)
    nome_latino     = models.CharField(max_length=120)
    data_insercao   = models.DateTimeField(auto_now_add=True)
    actualizacao    = models.DateTimeField(auto_now=True)
    zonas           = models.ManyToManyField("Zona",blank=True )
    def __str__(self):
        return self.nome
</code>```

I believe I have posted all the relevant code to this particular case.

Thanks again!

答:
models.py

```<code>class Zona(models.Model):
    codigo = models.CharField(max_length=120)
    area            = models.CharField(max_length=120)
    especies        = models.ManyToManyField("Especie", blank=True)

    def __str__(self):
        return self.codigo

    def get_especies(self):
        return self.especies.all().values_list('nome', flat=True)
</code>```

serializers.py

```<code>class ZonaSerializer(serializers.ModelSerializer):
    especies = serializers.ReadOnlyField(source='get_especies')
</code>```

Body:
im new to Django (and to the DjangoREST framework)and and I've been struggling for a while with the following:

I want for "especies" (apologies for the portuguese..) to be a vector with the names of the model Especies(scroll down pls) and instead this is giving me the id corresponding to the Especie.

"especies": [
            13,
            14
        ]

I want, for example:

"especies": [
            Z1,
            Z2
        ]

Thanks in advance!

The JSON parsed:

    {
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
        "codigo": "Z3",
        "area": "Z_tres",
        "especies": [
            13,
            14
        ],
        "id": 17
    }
    ]
}

FROM THE DJANGO REST APP:

views.py

from django.shortcuts import render
from species.models import Especie, Zona, EspecieZona
from rest_framework import viewsets
from rest.serializers import ZonaSerializer

class ZonaViewSet(viewsets.ModelViewSet):
    queryset = Zona.objects.all()
    serializer_class = ZonaSerializer

serializers.py

from species.models import Zona
from rest_framework import serializers

class ZonaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Zona
        fields = ('codigo', 'area', 'especies', 'id')

The models.py on this app is empty.

FROM THE MAIN APP

models.py

from django.db import models

class Zona(models.Model):
    codigo          = models.CharField(max_length=120)
    area            = models.CharField(max_length=120)
    especies        = models.ManyToManyField("Especie", blank=True)
    def __str__(self):
        return self.codigo

class Especie(models.Model):
    nome            = models.CharField(max_length=120)
    nome_latino     = models.CharField(max_length=120)
    data_insercao   = models.DateTimeField(auto_now_add=True)
    actualizacao    = models.DateTimeField(auto_now=True)
    zonas           = models.ManyToManyField("Zona",blank=True )
    def __str__(self):
        return self.nome

I believe I have posted all the relevant code to this particular case.

Thanks again!

Body:
models.py

class Zona(models.Model):
    codigo = models.CharField(max_length=120)
    area            = models.CharField(max_length=120)
    especies        = models.ManyToManyField("Especie", blank=True)

    def __str__(self):
        return self.codigo

    def get_especies(self):
        return self.especies.all().values_list('nome', flat=True)

serializers.py

class ZonaSerializer(serializers.ModelSerializer):
    especies = serializers.ReadOnlyField(source='get_especies')


问:
i am getting zero values of longitude and latitude in google maps in android studio
Here is my MapsActivity.java code, I am getting zero values for longitude and latitude after placing a marker on map and after calling getCurrentlocation(). What is going wrong?

```<code>public class MapsActivity extends FragmentActivity implements
        OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        GoogleMap.OnMarkerDragListener,
        GoogleMap.OnMapLongClickListener,
        View.OnClickListener {

    //Our Map
    private GoogleMap mMap;

    //To store longitude and latitude from map
    private double longitude;
    private double latitude;

    //Buttons
    private ImageButton buttonSave;
    private ImageButton buttonCurrent;
    private ImageButton buttonView;

    //Google ApiClient
    private GoogleApiClient googleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        //Initializing googleapi client
        googleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        //Initializing views and adding onclick listeners
        buttonSave = (ImageButton) findViewById(R.id.buttonSave);
        buttonCurrent = (ImageButton) findViewById(R.id.buttonCurrent);
        buttonView = (ImageButton) findViewById(R.id.buttonView);
        buttonSave.setOnClickListener(this);
        buttonCurrent.setOnClickListener(this);
        buttonView.setOnClickListener(this);
    }

    @Override
    protected void onStart() {
        googleApiClient.connect();
        super.onStart();
    }

    @Override
    protected void onStop() {
        googleApiClient.disconnect();
        super.onStop();
    }

    //Getting current location
    private void getCurrentLocation() {
        mMap.clear();
        //Creating a location object
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        if (location != null) {
            //Getting longitude and latitude
            longitude = location.getLongitude();
            latitude = location.getLatitude();

            //moving the map to location
            moveMap();
        }
    }

    //Function to move the map
    private void moveMap() {
        //String to display current latitude and longitude
        String msg = latitude + ", "+longitude;

        //Creating a LatLng Object to store Coordinates
        LatLng latLng = new LatLng(latitude, longitude);

        //Adding marker to map
        mMap.addMarker(new MarkerOptions()
                .position(latLng) //setting position
                .draggable(true) //Making the marker draggable
                .title("Current Location")); //Adding a title

        //Moving the camera
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

        //Animating the camera
        mMap.animateCamera(CameraUpdateFactory.zoomTo(15));

        //Displaying current coordinates in toast
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        LatLng latLng = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(latLng).draggable(true));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mMap.setOnMarkerDragListener(this);
        mMap.setOnMapLongClickListener(this);
    }

    @Override
    public void onConnected(Bundle bundle) {
        getCurrentLocation();
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    public void onMapLongClick(LatLng latLng) {
        //Clearing all the markers
        mMap.clear();

        //Adding a new marker to the current pressed position
        mMap.addMarker(new MarkerOptions()
                .position(latLng)
                .draggable(true));
        String msg = latitude + ", "+longitude;
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

    }

    @Override
    public void onMarkerDragStart(Marker marker) {

    }

    @Override
    public void onMarkerDrag(Marker marker) {

    }

    @Override
    public void onMarkerDragEnd(Marker marker) {
        //Getting the coordinates
        latitude = marker.getPosition().latitude;
        longitude = marker.getPosition().longitude;

        //Moving the map
        moveMap();
    }

    @Override
    public void onClick(View v) {
        if(v == buttonCurrent){
            getCurrentLocation();
            moveMap();
        }
    }
}
</code>```

答: GetLastLocation only returns a location if one is available.  99% of the time it won't be.  Use requestLocationUpdates or requestSingleUpdate to ensure a location is acquired (note both of these are asynchronous functions, as getting a location takes time).</p>

Body:
Here is my MapsActivity.java code, I am getting zero values for longitude and latitude after placing a marker on map and after calling getCurrentlocation(). What is going wrong?

public class MapsActivity extends FragmentActivity implements
        OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        GoogleMap.OnMarkerDragListener,
        GoogleMap.OnMapLongClickListener,
        View.OnClickListener {

    //Our Map
    private GoogleMap mMap;

    //To store longitude and latitude from map
    private double longitude;
    private double latitude;

    //Buttons
    private ImageButton buttonSave;
    private ImageButton buttonCurrent;
    private ImageButton buttonView;

    //Google ApiClient
    private GoogleApiClient googleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        //Initializing googleapi client
        googleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        //Initializing views and adding onclick listeners
        buttonSave = (ImageButton) findViewById(R.id.buttonSave);
        buttonCurrent = (ImageButton) findViewById(R.id.buttonCurrent);
        buttonView = (ImageButton) findViewById(R.id.buttonView);
        buttonSave.setOnClickListener(this);
        buttonCurrent.setOnClickListener(this);
        buttonView.setOnClickListener(this);
    }

    @Override
    protected void onStart() {
        googleApiClient.connect();
        super.onStart();
    }

    @Override
    protected void onStop() {
        googleApiClient.disconnect();
        super.onStop();
    }

    //Getting current location
    private void getCurrentLocation() {
        mMap.clear();
        //Creating a location object
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        if (location != null) {
            //Getting longitude and latitude
            longitude = location.getLongitude();
            latitude = location.getLatitude();

            //moving the map to location
            moveMap();
        }
    }

    //Function to move the map
    private void moveMap() {
        //String to display current latitude and longitude
        String msg = latitude + ", "+longitude;

        //Creating a LatLng Object to store Coordinates
        LatLng latLng = new LatLng(latitude, longitude);

        //Adding marker to map
        mMap.addMarker(new MarkerOptions()
                .position(latLng) //setting position
                .draggable(true) //Making the marker draggable
                .title("Current Location")); //Adding a title

        //Moving the camera
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

        //Animating the camera
        mMap.animateCamera(CameraUpdateFactory.zoomTo(15));

        //Displaying current coordinates in toast
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        LatLng latLng = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(latLng).draggable(true));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mMap.setOnMarkerDragListener(this);
        mMap.setOnMapLongClickListener(this);
    }

    @Override
    public void onConnected(Bundle bundle) {
        getCurrentLocation();
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    public void onMapLongClick(LatLng latLng) {
        //Clearing all the markers
        mMap.clear();

        //Adding a new marker to the current pressed position
        mMap.addMarker(new MarkerOptions()
                .position(latLng)
                .draggable(true));
        String msg = latitude + ", "+longitude;
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

    }

    @Override
    public void onMarkerDragStart(Marker marker) {

    }

    @Override
    public void onMarkerDrag(Marker marker) {

    }

    @Override
    public void onMarkerDragEnd(Marker marker) {
        //Getting the coordinates
        latitude = marker.getPosition().latitude;
        longitude = marker.getPosition().longitude;

        //Moving the map
        moveMap();
    }

    @Override
    public void onClick(View v) {
        if(v == buttonCurrent){
            getCurrentLocation();
            moveMap();
        }
    }
}


问:
How do I test script on my website that detects country location?
I have a website that is hosted with Adobe Business Catalyst.  I have the following liquid code that checks for country location and redirects the user accordingly:

```<code><script> window.location =
    {% if globals.visitor.country == 'AU' %}
    "/au"
    {% elsif globals.visitor.country == 'US' %}
        "/us"
    {% elsif globals.visitor.country == 'GB' %}
        "/gb"
    {% else %}
        "/store-unavailable"
     {% endif %}
</script>
</code>```

I am located in Australia, so I can only check the country location for Australia.  How would I test the script for the other countries?

Thanks

答:
You should use a proxy server to trick the browser that you are coming from a different country.

You can also google "test website from different country" and you will find many solutions.

Body:
I have a website that is hosted with Adobe Business Catalyst.  I have the following liquid code that checks for country location and redirects the user accordingly:

I am located in Australia, so I can only check the country location for Australia.  How would I test the script for the other countries?

Thanks


问:
Change base URL of generated S3 link using AWS SDK (PHP)
I want to create presigned S3 URL as mentioned here:
https://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/s3-presigned-url.html

My code is quite similar to the example mentioned in the url:

```<code>$sdk = new Aws\Sdk( [
    'region' => 'eu-west-2',
    'version' => 'latest',
] );

$s3Client = $sdk->createS3();

$cmd = $s3Client->getCommand('GetObject', [
    'Bucket' => 'books.com',
    'Key'    => 'testKey'
]);

$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');

// Get the actual presigned-url
$presignedUrl = (string) $request->getUri();
</code>```

The above generates urls like so:

https://s3.eu-west-2.amazonaws.com/books.com/testKey?X-Amz-Content-Sha256=....

This is as expected. However my S3 bucket has Static Website Hosting and I use a CNAME record allowing me to use a different base url.

Therefore I want the following URL instead:

http://books.com/my-bucket/testKey?X-Amz-Content-Sha256=....

How can I do this?

答:
You can set the endpoint to your bucket domain name:

```<code>$sdk = new Aws\Sdk( [
    'region' => 'eu-west-2',
    'version' => 'latest',
    'endpoint' => 'http://books.com',
    'bucket_endpoint' => true
] );
</code>```

This will generate a signed URL that looks like this:

http://books.com/testKey?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAI2V4Lxxxxxxxxxxx%2F20171116%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20171116T191003Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=0b735cb661b1d2e25c7f5b477d4c657f160a85aa53bee3ea91244340f6d37dee

Body:
I want to create presigned S3 URL as mentioned here:
https://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/s3-presigned-url.html

My code is quite similar to the example mentioned in the url:

$sdk = new Aws\Sdk( [
    'region' => 'eu-west-2',
    'version' => 'latest',
] );

$s3Client = $sdk->createS3();

$cmd = $s3Client->getCommand('GetObject', [
    'Bucket' => 'books.com',
    'Key'    => 'testKey'
]);

$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');

// Get the actual presigned-url
$presignedUrl = (string) $request->getUri();

The above generates urls like so:

https://s3.eu-west-2.amazonaws.com/books.com/testKey?X-Amz-Content-Sha256=....

This is as expected. However my S3 bucket has Static Website Hosting and I use a CNAME record allowing me to use a different base url.

Therefore I want the following URL instead:

http://books.com/my-bucket/testKey?X-Amz-Content-Sha256=....

How can I do this?

Body:
You can set the endpoint to your bucket domain name:

$sdk = new Aws\Sdk( [
    'region' => 'eu-west-2',
    'version' => 'latest',
    'endpoint' => 'http://books.com',
    'bucket_endpoint' => true
] );

This will generate a signed URL that looks like this:

http://books.com/testKey?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAI2V4Lxxxxxxxxxxx%2F20171116%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20171116T191003Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=0b735cb661b1d2e25c7f5b477d4c657f160a85aa53bee3ea91244340f6d37dee


问:
How can I return a value from the main function when using a nested forEach loop without a temporary variable?
I would like to return primaryNumber without having to use a an extra variable for it.

I would like an arrow statement function that just returns element.number without needing primaryNumber. As it stands the inner forEach is in a different scope so I can't just return element.number from findPrimaryNumber(). Is there a good solution?

```<code>function findPrimaryNumber(gender, naturalExpressionYearOfBirth) {
    let primaryNumber, primaryNumberGenderObject;
    if (gender === "f") {
        primaryNumberGenderObject = primaryNumberFemales;
    } else if (gender === "m") {
        primaryNumberGenderObject = primaryNumberMales;
    }

    primaryNumberGenderObject.forEach(element => {
        element.year.forEach(yearWeAreLookingFor => {
            if (yearWeAreLookingFor === naturalExpressionYearOfBirth) {
                primaryNumber = element.number;
            }
        });
    });
    return primaryNumber;
}
</code>```

Here is an example of the object it is searching:

```<code>const primaryNumberMales = [{
    name: "Fire Yin",
    number: 9,
    year: [1910,
      1919,
      1928,
      1937,
      1946,
      1955,
      1964,
      1973,
      1982,
      1991,
      2000,
      2009,
      2018
    ]
  },
  {
    name: "Mountain Yang",
    number: 8,
    year: [1911,
      1920,
      1929,
      1938,
      1947,
      1956,
      1965,
      1974,
      1983,
      1992,
      2001,
      2010,
      2019,
    ]
  },
  {
    name: "Lake Yin",
    number: 7,
    year: [1912,
      1921,
      1930,
      1939,
      1948,
      1957,
      1966,
      1975,
      1984,
      1993,
      2002,
      2011,
      2020,
    ]
  },
  {
    name: "Sky Yang",
    number: 6,
    year: [1913,
      1922,
      1931,
      1940,
      1949,
      1958,
      1967,
      1976,
      1985,
      1994,
      2003,
      2012,
      2021,
    ]
  },
  {
    name: "Earth Core Yang",
    number: 5,
    year: [1914,
      1923,
      1932,
      1941,
      1950,
      1959,
      1968,
      1977,
      1986,
      1995,
      2004,
      2013,
      2022,
    ]
  },
  {
    name: "Wind Yin",
    number: 4,
    year: [1915,
      1924,
      1933,
      1942,
      1951,
      1960,
      1969,
      1978,
      1987,
      1996,
      2005,
      2014,
      2023,
    ]
  },
  {
    name: "Thunder Yang",
    number: 3,
    year: [1916,
      1925,
      1934,
      1943,
      1952,
      1961,
      1970,
      1979,
      1988,
      1997,
      2006,
      2015,
      2024,
    ]
  },
  {
    name: "Earth Yin",
    number: 2,
    year: [1917,
      1926,
      1935,
      1944,
      1953,
      1962,
      1971,
      1980,
      1989,
      1998,
      2007,
      2016,
      2025,
    ]
  },
  {
    name: "Sea Yang",
    number: 1,
    year: [1918,
      1927,
      1936,
      1945,
      1954,
      1963,
      1972,
      1981,
      1990,
      1999,
      2008,
      2017,
      2026,
    ]
  }
];
</code>```

答:
You can use find:

```<code>   primaryNumberGenderObject.find(element => {
      return element.year.includes(naturalExpressionYearOfBirth)
   }).number;
</code>```

This will find the first element where the callback return true.

Body:
You can use find:

   primaryNumberGenderObject.find(element => {
      return element.year.includes(naturalExpressionYearOfBirth)
   }).number;

This will find the first element where the callback return true.


问:
Calculate Time Remaining
What's a good algorithm for determining the remaining time for something to complete?  I know how many total lines there are, and how many have completed already, how should I estimate the time remaining?</p>

答:
there is no standard algorithm i know of, my sugestion would be:

Create a variable to save the %

Calculate the complexity of the task you wish to track(or an estimative of it)

Put increments to the % from time to time as you would see fit given the complexity.

You probably seen programs where the load bar runs much faster in one point than in another. Well that's pretty much because this is how they do it. (though they probably just put increments at regular intervals in the main wrapper)

OwnerDisplayName: Aaron Smith

Title: Calculate Time Remaining

OwnerDisplayName: fmsf


问:
Linking Matlab with C#
Is there a way that we can link a GUI C# program with any 'm' file in a way that we can give the 'm' file an input from the C# program?

For example, the m file here is a function that rotates any given images by 'a' degree, where the degree is an input from the C# program.

Thanks a lot :)

答:
You can automate MATLAB from your C# GUI application using COM, see https://ch.mathworks.com/help/matlab/call-matlab-com-automation-server.html.

See as well the following code example:

```<code>MLApp.MLApp m = new MLApp.MLApp();
double x = 0.5;
m.PutWorkspaceData("x", "base", (object)x);
m.Execute("y=sin(x);"); // here you could execute your m-file
double y = m.GetVariable("y", "base");
m.Quit();
</code>```

Make sure you add a reference to Matlab Application (Version x.x) Type Library in your C# GUI application.

Title: Linking Matlab with C#

Body:
You can automate MATLAB from your C# GUI application using COM, see https://ch.mathworks.com/help/matlab/call-matlab-com-automation-server.html.

See as well the following code example:

MLApp.MLApp m = new MLApp.MLApp();
double x = 0.5;
m.PutWorkspaceData("x", "base", (object)x);
m.Execute("y=sin(x);"); // here you could execute your m-file
double y = m.GetVariable("y", "base");
m.Quit();

Make sure you add a reference to Matlab Application (Version x.x) Type Library in your C# GUI application.


问:
Sending/Parsing multiple JSON objects
I have a Sinatra server that is returning multiple JSON objects from the database in a streaming manner.  The objects would look like:

```<code>{"a": 1, "b": 2, "c": 3}
{"a": 4, "b": 5, "c": 6}
...
</code>```

but this is invalid JSON.  I can add a hack into Sinatra's event processing (manually injecting the missing array delimiters) to make the response look like:

```<code>[
{"a": 1, "b": 2, "c": 3}
, {"a": 4, "b": 5, "c": 6}
]
</code>```

which is valid JSON now, but this technique is inelegant.  Is there some way to do this client-side?  Basically, what I want is to have a JavaScript function read a string and consume a valid JSON object, and then return to me the JSON object and the remainder of the string, iteratively being called until the entire string is consumed.

答:
o.string  is json Object.

add some string like  "new"  to array of objects or multiple json objects.

for eg:

```<code>json object----

{"id":2,"method":"listWirings","params":{"language":"anonymousLanguage","name":"mytest","working":"{\"modules\":[{\"config\":{\"position\":[186,59],\"xtype\":\"WireIt.ImageContainer\"},\"name\":\"Start\",\"value\":{}},{\"config\":{\"position\":[188,265],\"xtype\":\"WireIt.ImageContainer\"},\"name\":\"Stop\",\"value\":{}}],\"properties\":{\"description\":\"gfd\",\"name\":\"gf\"},\"wires\":[{\"src\":{\"moduleId\":0,\"terminal\":\"_OUTPUT\"},\"tgt\":{\"moduleId\":1,\"terminal\":\"StpIn\"}}]}"},"version":"json-rpc-2.0"}new

  var str = o.toString();
                var s = str.split("new");
                for (var i = 0; i < s.length-1; i++)
                {
                    var r = YAHOO.lang.JSON.parse(s[i]);
                }
</code>```

hope this will to parse multiple json objects .

Title: Sending/Parsing multiple JSON objects

Body:
I have a Sinatra server that is returning multiple JSON objects from the database in a streaming manner.  The objects would look like:

{"a": 1, "b": 2, "c": 3}
{"a": 4, "b": 5, "c": 6}
...

but this is invalid JSON.  I can add a hack into Sinatra's event processing (manually injecting the missing array delimiters) to make the response look like:

[
{"a": 1, "b": 2, "c": 3}
, {"a": 4, "b": 5, "c": 6}
]

which is valid JSON now, but this technique is inelegant.  Is there some way to do this client-side?  Basically, what I want is to have a JavaScript function read a string and consume a valid JSON object, and then return to me the JSON object and the remainder of the string, iteratively being called until the entire string is consumed.

Body:
o.string  is json Object.

add some string like  "new"  to array of objects or multiple json objects.

for eg:

json object----

{"id":2,"method":"listWirings","params":{"language":"anonymousLanguage","name":"mytest","working":"{\"modules\":[{\"config\":{\"position\":[186,59],\"xtype\":\"WireIt.ImageContainer\"},\"name\":\"Start\",\"value\":{}},{\"config\":{\"position\":[188,265],\"xtype\":\"WireIt.ImageContainer\"},\"name\":\"Stop\",\"value\":{}}],\"properties\":{\"description\":\"gfd\",\"name\":\"gf\"},\"wires\":[{\"src\":{\"moduleId\":0,\"terminal\":\"_OUTPUT\"},\"tgt\":{\"moduleId\":1,\"terminal\":\"StpIn\"}}]}"},"version":"json-rpc-2.0"}new

  var str = o.toString();
                var s = str.split("new");
                for (var i = 0; i < s.length-1; i++)
                {
                    var r = YAHOO.lang.JSON.parse(s[i]);
                }

hope this will to parse multiple json objects .


问:
Why is cmp( ) useful?
According to the doc and this tutorial,

cmp() returns -1 if x < y

and

cmp() returns 0 if  x == y

and

cmp() returns 1 if  x > y

The tutorial also said that

cmp() returns the sign of the difference of two numbers

I don't really get what  sign of the difference of two numbers means. Doesn't that mean that it returns a value when the sign of numbers aren't equal? Since...

```<code>cmp(80, 100) :  -1      # both have positive sign.
cmp(180, 100) :  1      # both also have positive sign.
cmp(-80, 100) :  -1
cmp(80, -100) :  1
</code>```

**Note: code from the tutorial.*

Despite my confusion in sign differences, I can't really think of why do we need a built-in function to return a value of -1 when x < y.

Isn't the function cmp( ) easily implemented ? Is there any reason why Python creators keep cmp( ) function, or is there any hidden usage of this Python's cmp( ) function ?

答:
Another use case: Finding the sign (- / +) of a number

If you want to find out, what the sign (+/-) of a number is, you can easily use 0 as the second argument to the cmp function

```<code>cmp(-123, 0) #returns -1
cmp( 123, 0) #returns  1
</code>```

ContentLicense: CC BY-SA 4.0

Title: Why is cmp( ) useful?

Body:
According to the doc and this tutorial,

cmp() returns -1 if x < y

and

cmp() returns 0 if  x == y

and

cmp() returns 1 if  x > y

The tutorial also said that

cmp() returns the sign of the difference of two numbers

I don't really get what  sign of the difference of two numbers means. Doesn't that mean that it returns a value when the sign of numbers aren't equal? Since...

cmp(80, 100) :  -1      # both have positive sign.
cmp(180, 100) :  1      # both also have positive sign.
cmp(-80, 100) :  -1
cmp(80, -100) :  1

**Note: code from the tutorial.*

Despite my confusion in sign differences, I can't really think of why do we need a built-in function to return a value of -1 when x < y.

Isn't the function cmp( ) easily implemented ? Is there any reason why Python creators keep cmp( ) function, or is there any hidden usage of this Python's cmp( ) function ?

Body:
Another use case: Finding the sign (- / +) of a number

If you want to find out, what the sign (+/-) of a number is, you can easily use 0 as the second argument to the cmp function

cmp(-123, 0) #returns -1
cmp( 123, 0) #returns  1


问:
Returning multiple values from a C++ function
Is there a preferred way to return multiple values from a C++ function?  For example, imagine a function that divides two integers and returns both the quotient and the remainder.  One way I commonly see is to use reference parameters:

```<code>void divide(int dividend, int divisor, int& quotient, int& remainder);
</code>```

A variation is to return one value and pass the other through a reference parameter:

```<code>int divide(int dividend, int divisor, int& remainder);
</code>```

Another way would be to declare a struct to contain all of the results and return that:

```<code>struct divide_result {
    int quotient;
    int remainder;
};

divide_result divide(int dividend, int divisor);
</code>```

Is one of these ways generally preferred, or are there other suggestions?

Edit: In the real-world code, there may be more than two results.  They may also be of different types.

答:
rather than returning multiple values,just return one of them and make a reference of others in the required function for eg:</p>

```<code>int divide(int a,int b,int quo,int &rem)
</code>```

OwnerDisplayName: Fred Larson

Body:
Is there a preferred way to return multiple values from a C++ function?  For example, imagine a function that divides two integers and returns both the quotient and the remainder.  One way I commonly see is to use reference parameters:

void divide(int dividend, int divisor, int& quotient, int& remainder);

A variation is to return one value and pass the other through a reference parameter:

int divide(int dividend, int divisor, int& remainder);

Another way would be to declare a struct to contain all of the results and return that:

struct divide_result {
    int quotient;
    int remainder;
};

divide_result divide(int dividend, int divisor);

Is one of these ways generally preferred, or are there other suggestions?

Edit: In the real-world code, there may be more than two results.  They may also be of different types.

LastEditorDisplayName: Fred Larson

Body:
rather than returning multiple values,just return one of them and make a reference of others in the required function for eg:

int divide(int a,int b,int quo,int &rem)


问:
hibernate.jdbc.time_zone setting is ignored in Wildfly Swarm application
I am building an application using Wildfly Swarm (2017.11.0), which requires ZonedDateTime objects to be persisted in UTC.

Currently, I am using the ExamplesDS JTA data source and configured following property:

```<code><property name="hibernate.jdbc.time_zone" value="UTC"/>
</code>```

As the Swarm JPA dependency declares Hibernate 5.0.x and JPA 2.1 as dependencies, I manually included

```<code><dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.2.12.Final</version>
</dependency>
</code>```

and

```<code><dependency>
 <groupId>javax.persistence</groupId>
 <artifactId>javax.persistence-api</artifactId>
 <version>2.2</version>
</dependency>
</code>```

and set them to non-provided.

However, the property is completely ignored by Hibernate, which persists and fetches the time stamps as a ZonedDateTimewith local zone. Other properties inside the persistence.xml are correctly recognized.

At the moment, I am not sure where the issue is located and how to solve it. Also, when I am running Wildfly Swarm with the jvm argument -Duser.timezone=UTC, nothing changes. Is this maybe an issue of the ExamplesDS or is Wildfly Swarm ignoring my dependency declarations? If so, how can I ensure that Swarm uses the correct version?

答:
In many aspects, WildFly Swarm behaves just like WildFly. You can't upgrade Hibernate/JPA like this, nor any other Java EE spec.

There are probably ways to do it, such as changing directly the content of m2repo inside the Swarm uberjar, or manipulating with subsystems and modules, but you shouldn't expect that to work flawlessly.

Body:
I am building an application using Wildfly Swarm (2017.11.0), which requires ZonedDateTime objects to be persisted in UTC.

Currently, I am using the ExamplesDS JTA data source and configured following property:

<property name="hibernate.jdbc.time_zone" value="UTC"/>

As the Swarm JPA dependency declares Hibernate 5.0.x and JPA 2.1 as dependencies, I manually included

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.2.12.Final</version>
</dependency>

and

<dependency>
 <groupId>javax.persistence</groupId>
 <artifactId>javax.persistence-api</artifactId>
 <version>2.2</version>
</dependency>

and set them to non-provided.

However, the property is completely ignored by Hibernate, which persists and fetches the time stamps as a ZonedDateTimewith local zone. Other properties inside the persistence.xml are correctly recognized.

At the moment, I am not sure where the issue is located and how to solve it. Also, when I am running Wildfly Swarm with the jvm argument -Duser.timezone=UTC, nothing changes. Is this maybe an issue of the ExamplesDS or is Wildfly Swarm ignoring my dependency declarations? If so, how can I ensure that Swarm uses the correct version?


问:
Subscription with credit/debit card with Paypal Developer API Standard
I'm creating a website for a customer, he has a service that will be billed monthly (same price). The user should be able to pay with a PayPal account or with his debit/credit card.

I read the PayPal documentation according to my understanding the PayPal standard (the account that my customer has) just give the option of paying with a button and the user should use the PayPal account.

I want to know if this is possible because I didn't see any reference to it in the documentation or if it depends on the country of my customer (some answers say so) how I know in what countries is available (he is from Spain, but I'm from the Dominican Republic so maybe I wouldn't be able to test this feature).

答:
PayPal country availability is subject to change.

Please see this link: http://smallbusiness.chron.com/country-doesnt-work-paypal-66099.html

What Country Doesn't Work With PayPal?

by John Lister

PayPal is available in some form in 191 countries as of May 2013. PayPal only offers limited service in some countries. It has no dealings whatsoever in some other countries, many of which are in the Middle East or Africa.

Availability

As of April 2013, PayPal offered full locally-based services in 26 countries. In another 18 countries you can have a PayPal account and transfer money to a local or US bank account. In India and Vietnam you can only transfer money to a local bank account. In a further 64 countries you can only withdraw money to a US bank account. In 83 other countries you can have a PayPal account but cannot withdraw money to a bank account.

No Availability

PayPal does not maintain a list of countries where it does not provide any service. However, a comparison of the United Nations' list of member states and the PayPal list of countries with some service shows 28 countries without service as of May 2013. These are: Afghanistan, Bangladesh, Cameroon, Central African Republic, Cote D'Ivoire (Ivory Coast), Democratic People's Republic of Korea (North Korea), Equatorial Guinea, Gabon, Ghana, Haiti, Iran, Iraq, Lebanon, Liberia, Libya, Monaco, Moldova, Montenegro, Myanmar, Pakistan, Paraguay, Saint Lucia, South Sudan, Sudan, Syria, Timor-Leste, Uzbekistan and Zimbabwe.

Rationale

PayPal does not publicly detail why it does not service particular countries. Media speculation suggests common reasons could include insufficient regulation and security in a country's banking system, failure of a country to comply with U.S. tax law, or a U.S. trade ban affecting a country. The availability of PayPal in countries can and does change. For example, in April 2013 PayPal became available in Egypt for the first time.

Restriction

Although PayPal lets you change your address when you move, you cannot change your address to one in another country, even if PayPal operates in that country. If you move abroad, you have two options. You can close your account and open a new one, or you can have two accounts -- one account in your old country and one in the new one. However, the two accounts must be of different types (premier, personal or business) and must each be linked to a different e-mail address and bank account.


问:
xstl apply-template (call tempalate) with variable and use in xsl:evaluate
I have the following xml:

```<code><pi:Payroll_Extract_Employees xmlns:pi="urn:com.workday/picof">
   <pi:company>
      <pi:Employee>
         <pi:name>John Andrews</pi:name>
         <pi:age>23</pi:age>
         <pi:salary>4000</pi:salary>
         <pi:division>Accounting</pi:division>
      </pi:Employee>
   </pi:company>
</pi:Payroll_Extract_Employees>
</code>```

I am using this transformation:

```<code><xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:pi="urn:com.workday/picof">
    <xsl:output method="text"/>
    <xsl:template match="pi:Payroll_Extract_Employees/pi:company">
        <xsl:variable name="tabsNames">
            <entry>
                <spreadSheetName>Payroll Data for Taiwan</spreadSheetName>
                <values>
                    <value>
                        <header>Chinese Name</header>
                        <data>/pi:Name</data>
                    </value>
                </values>
            </entry>
        </xsl:variable>
        <xsl:variable name="currentNode" select="."/>
        <xsl:for-each select="$tabsNames/entry">
            <xsl:variable name="dataValues" select="values/value/data"/>

            <xsl:call-template name="employeeRows">
                <xsl:with-param name="rows" select="$dataValues" as="element()*"/>
                <xsl:with-param name="currentNode" select="$currentNode" as="element()"/>
            </xsl:call-template>

        </xsl:for-each>
    </xsl:template>
    <xsl:template name="employeeRows">
        <xsl:param name="rows" select="."/>
        <xsl:param name="currentNode" select="."/>

        <xsl:for-each select="$currentNode/pi:Employee">
            <xsl:variable name="employee" select="." as="element()"/>
            <xsl:for-each select="$rows">
                <xsl:variable name="path" select="."/>
                <xsl:value-of>
                    <xsl:evaluate xpath="$employee || $path" context-item="."/>
                    <!--<xsl:value-of select="$employee/pi:name"/>-->
                </xsl:value-of>
            </xsl:for-each>
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>
</code>```

Here I am creating a map $tabNames and the would like to pass map together with current node to employeeRows template. Instead of data values for "rows" parameter I get entire map and instead of current node (pi:Payroll_Extract_Employees/pi:company) for currentNode parameter I receive the same map as for the "rows" parameter.
The second problem is that xsl:evaluates changes $employee to a value I would like following to give me the same output

```<code><xsl:evaluate xpath="$employee || $path" context-item="."/>
</code>```

as this

```<code><xsl:value-of select="$employee/pi:Name"/>
</code>```

What I have so far throws an error here:

```<code><xsl:evaluate xpath="$employee || $path" context-item="."/>
</code>```

Error message:

System ID: C:\Users\przemekb\AppData\Local\Temp\Untitled4.xsl
Severity: fatal
Description: Static error in XPath expression supplied to xsl:evaluate: Unexpected token name "Andrews" beyond end of expression. Expression: { John Andrews 23 4000 Accounting pi:Name}
Start location: 36:42
Length: 1

答:
Perhaps your

```<code><xsl:evaluate xpath="$employee || $path" context-item="."/>
</code>```

should be either

```<code><xsl:evaluate xpath="'$employee' || $path">
  <xsl:with-param name="employee" select="$employee"/>
</xsl:evaluate>
</code>```

or simply

```<code><xsl:evaluate xpath="$path" context-item="$employee"/>
</code>```

Body:
I have the following xml:

<pi:Payroll_Extract_Employees xmlns:pi="urn:com.workday/picof">
   <pi:company>
      <pi:Employee>
         <pi:name>John Andrews</pi:name>
         <pi:age>23</pi:age>
         <pi:salary>4000</pi:salary>
         <pi:division>Accounting</pi:division>
      </pi:Employee>
   </pi:company>
</pi:Payroll_Extract_Employees>

I am using this transformation:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:pi="urn:com.workday/picof">
    <xsl:output method="text"/>
    <xsl:template match="pi:Payroll_Extract_Employees/pi:company">
        <xsl:variable name="tabsNames">
            <entry>
                <spreadSheetName>Payroll Data for Taiwan</spreadSheetName>
                <values>
                    <value>
                        Chinese Name
                        <data>/pi:Name</data>
                    </value>
                </values>
            </entry>
        </xsl:variable>
        <xsl:variable name="currentNode" select="."/>
        <xsl:for-each select="$tabsNames/entry">
            <xsl:variable name="dataValues" select="values/value/data"/>

            <xsl:call-template name="employeeRows">
                <xsl:with-param name="rows" select="$dataValues" as="element()*"/>
                <xsl:with-param name="currentNode" select="$currentNode" as="element()"/>
            </xsl:call-template>

        </xsl:for-each>
    </xsl:template>
    <xsl:template name="employeeRows">
        <xsl:param name="rows" select="."/>
        <xsl:param name="currentNode" select="."/>

        <xsl:for-each select="$currentNode/pi:Employee">
            <xsl:variable name="employee" select="." as="element()"/>
            <xsl:for-each select="$rows">
                <xsl:variable name="path" select="."/>
                <xsl:value-of>
                    <xsl:evaluate xpath="$employee || $path" context-item="."/>

                </xsl:value-of>
            </xsl:for-each>
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

Here I am creating a map $tabNames and the would like to pass map together with current node to employeeRows template. Instead of data values for "rows" parameter I get entire map and instead of current node (pi:Payroll_Extract_Employees/pi:company) for currentNode parameter I receive the same map as for the "rows" parameter.
The second problem is that xsl:evaluates changes $employee to a value I would like following to give me the same output

<xsl:evaluate xpath="$employee || $path" context-item="."/>

as this

<xsl:value-of select="$employee/pi:Name"/>

What I have so far throws an error here:

<xsl:evaluate xpath="$employee || $path" context-item="."/>

Error message:

System ID: C:\Users\przemekb\AppData\Local\Temp\Untitled4.xsl
Severity: fatal
Description: Static error in XPath expression supplied to xsl:evaluate: Unexpected token name "Andrews" beyond end of expression. Expression: { John Andrews 23 4000 Accounting pi:Name}
Start location: 36:42
Length: 1

Body:
Perhaps your

<xsl:evaluate xpath="$employee || $path" context-item="."/>

should be either

<xsl:evaluate xpath="'$employee' || $path">
  <xsl:with-param name="employee" select="$employee"/>
</xsl:evaluate>

or simply

<xsl:evaluate xpath="$path" context-item="$employee"/>


问:
In App Purchase Never Completes
I have a single user who is experiencing difficulty when making an in app purchase. I've had 60-65 successful in app purchases, but this user has experienced problems a couple times. The in app-purchase is set up as a non-renewing subscription. I believe both times he's had problems he's been trying to make the purchase on the same day his subscription expired. Any idea why his in app purchase process never completes?

Here is how he describes what happens:

Step by step.
1. Subscription runs out
2. Click on renew
3. I have password protect on adding apps and paying for apps , so I go thru password and accepting charges.
4. Charges state accepted in app, however , when I click to use app it continually asks me to renew subscription. (Author note: I think he's referring to an alert controller I've put in the app for when their subscription date is earlier than today's date) Then when I attempt to pay again it says in app purchase already made. Attempted at least 5 times.
5. After each unsuccessful attempt to repurchase it just appears the app is in reloading mode. Has a thinking spinning wheel in middle of app  is best way to describe.

Here is the relevant code:

```<code>@IBAction func buyOneMonthTapped(_ sender: Any) {

        activity.startAnimating()
        activity.isHidden = false

        product_ID = **(removed)**
        purchaseLength = "onemonth"

        print("About to fetch the products")

        // We check that we are allowed to make the purchase.

        if (SKPaymentQueue.canMakePayments())
        {
            let productID:NSSet = NSSet(object: self.product_ID!);
            let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
            productsRequest.delegate = self;
            productsRequest.start();
            print("Fetching Products");

        }  else { print("can't make purchases")

            let cantPurchaseAlert = UIAlertController(title: "Can't Make Purchases", message: "You do not have the ability to make purchases on this device. Please check your settings and payment info and try again.", preferredStyle: .alert)
            cantPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                self.activity.isHidden = true
                self.activity.stopAnimating()
            }))

        }

    }

    @IBAction func buyOneYearTapped(_ sender: Any) {

        activity.startAnimating()
        activity.isHidden = false

        product_ID = **(removed)**
        purchaseLength = "oneyear"

        print("About to fetch the products")

        // We check that we are allowed to make the purchase.

        if (SKPaymentQueue.canMakePayments())
        {
            let productID:NSSet = NSSet(object: self.product_ID!);
            let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
            productsRequest.delegate = self;
            productsRequest.start();
            print("Fetching Products");

        }  else { print("can't make purchases")

            let cantPurchaseAlert = UIAlertController(title: "Can't Make Purchases", message: "You do not have the ability to make purchases on this device. Please check your settings and payment info and try again.", preferredStyle: .alert)
            cantPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                self.activity.isHidden = true
                self.activity.stopAnimating()
            }))

        }

    }

    func buyProduct(_ product: SKProduct){
        print("Sending the Payment Request to Apple");
        let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment);

    }

    func productsRequest (_ request: SKProductsRequest, didReceive response: SKProductsResponse) {

        let count : Int = response.products.count
        if (count>0) {
            let validProducts = response.products
            let validProduct: SKProduct = response.products[0] as SKProduct
            if (validProduct.productIdentifier == self.product_ID as String!) {
                print(validProduct.localizedTitle)
                print(validProduct.localizedDescription)

                print(validProduct.price)
                buyProduct(validProduct);
            } else {
                print(validProduct.productIdentifier)
            }
        } else {
            print("nothing")
        }
    }

    func request(_ request: SKRequest, didFailWithError error: Error) {
        print("Error Fetching product information")

        let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@*****.com", preferredStyle: .alert)
        failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            self.activity.isHidden = true
            self.activity.stopAnimating()
        }))

        ;
    }

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])    {
        print("Received Payment Transaction Response from Apple");

        for transaction:AnyObject in transactions {
            if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{

                switch trans.transactionState {
                case .purchased:
                    print("Product Purchased");
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)

                    subscriptionEndDate = userSettings.object(forKey: "subEnd") as? Date

                    let calendar = Calendar.current

                    let today = Date()

                    if purchaseLength == "onemonth" {

                        if (subscriptionEndDate as NSDate?)?.earlierDate(today) == today {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.month], value: 1, to: subscriptionEndDate!, options: [])!

                        } else {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.month], value: 1, to: today, options: [])!

                        } }

                    else  if purchaseLength == "oneyear" {

                        if (subscriptionEndDate as NSDate?)?.earlierDate(today) == today {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.year], value: 1, to: subscriptionEndDate!, options: [])!

                        } else {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.year], value: 1, to: today, options: [])!

                        }

                    }

                    print("added time")

                    let components = (calendar as NSCalendar).components([.day, .month, .year], from: subscriptionEndDate!)

                    let year = components.year
                    let month = components.month
                    let day = components.day

                    let testDate = "\(month!)/\(day!)/\(year!)"

                    if (subscriptionEndDate! as NSDate).laterDate(today) == subscriptionEndDate {

                        subscriptionMessageLabel.text = "Your subscription expires on:"
                        subscriptionLabel.text = "\(testDate)" }

                    else {

                        subscriptionMessageLabel.text = "There was an error in the purchase."
                        subscriptionLabel.text = "Please contact Support@UndauntedAthlete.com" }

                    userSettings.set(subscriptionEndDate, forKey: "subEnd")

                    ref.updateChildValues(["users/\(userID!)/subscriptionDate": testDate])

                    activity.isHidden = true
                    activity.stopAnimating()

                    break;

                case .failed:
                    print("Purchased Failed");
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)

                    let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@****.com", preferredStyle: .alert)
                    failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                        self.activity.isHidden = true
                        self.activity.stopAnimating()
                    }))

                    break

                case .restored:
                    print("Already Purchased");
                    SKPaymentQueue.default().restoreCompletedTransactions()

                    let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@*****.com", preferredStyle: .alert)
                    failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                        self.activity.isHidden = true
                        self.activity.stopAnimating()
                    }))

                default:
                    let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@*****.com", preferredStyle: .alert)
                    failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                        self.activity.isHidden = true
                        self.activity.stopAnimating()
                    }))

                    break
                }
            }
        }
    }
</code>```

答:
Reviewing your code there are a lot of potential issues that could be causing client side bugs.

I would suggest prefetching the SKProducts before displaying the UI to the user. This allows you to display the price before they initiate a purchase, which is good UX in my opinion.

Because you are storing the state of what product was requested at the controller level, there could be bugs introduced if a user is able to dispatch two separate taps, i.e. taps monthly then annual in rapid succession before you are able to disable the UI. This would mess your code up.

You should be checking canMakePayments earlier, preventing the user from ever initiating a purchase.

I would remove the order dependency from productRequest:didReceiveResponse:. Don't just assume the 0th product is the one you are looking for, request all products and search for the one you want.

The biggest mis-implementation is the way you are calculating the expiration date. Apple provides the expiration date in the receipt info, this is the proper way to get the expiration for a subscription product. This means fetching the receipt data, sending it to Apple (or ideally your backend) for verification. The date that a transaction is processed by your transaction queue observer and its actual purchase date are not the same. Relying on the receipt for the expiration date removes the need for your app to do the tracking and expiration calculation, which is likely the source of this bug. Using the receipt for your subscription source of truth will be the best way to get your IAP code to match Apple's.

I realize "rewrite your IAP code" probably isn't the answer you were looking for but there is a lot of code here and its likely an issue in some interaction between StoreKit and your app. You should have a look at how we do IAP at RevenueCat. It is a general implementation but it should give you an idea of how to properly interact with StoreKit.

Title: In App Purchase Never Completes

Body:
I have a single user who is experiencing difficulty when making an in app purchase. I've had 60-65 successful in app purchases, but this user has experienced problems a couple times. The in app-purchase is set up as a non-renewing subscription. I believe both times he's had problems he's been trying to make the purchase on the same day his subscription expired. Any idea why his in app purchase process never completes?

Here is how he describes what happens:

Step by step.
1. Subscription runs out
2. Click on renew
3. I have password protect on adding apps and paying for apps , so I go thru password and accepting charges.
4. Charges state accepted in app, however , when I click to use app it continually asks me to renew subscription. (Author note: I think he's referring to an alert controller I've put in the app for when their subscription date is earlier than today's date) Then when I attempt to pay again it says in app purchase already made. Attempted at least 5 times.
5. After each unsuccessful attempt to repurchase it just appears the app is in reloading mode. Has a thinking spinning wheel in middle of app  is best way to describe.

Here is the relevant code:

@IBAction func buyOneMonthTapped(_ sender: Any) {

        activity.startAnimating()
        activity.isHidden = false

        product_ID = **(removed)**
        purchaseLength = "onemonth"

        print("About to fetch the products")

        // We check that we are allowed to make the purchase.

        if (SKPaymentQueue.canMakePayments())
        {
            let productID:NSSet = NSSet(object: self.product_ID!);
            let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
            productsRequest.delegate = self;
            productsRequest.start();
            print("Fetching Products");

        }  else { print("can't make purchases")

            let cantPurchaseAlert = UIAlertController(title: "Can't Make Purchases", message: "You do not have the ability to make purchases on this device. Please check your settings and payment info and try again.", preferredStyle: .alert)
            cantPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                self.activity.isHidden = true
                self.activity.stopAnimating()
            }))

        }

    }

    @IBAction func buyOneYearTapped(_ sender: Any) {

        activity.startAnimating()
        activity.isHidden = false

        product_ID = **(removed)**
        purchaseLength = "oneyear"

        print("About to fetch the products")

        // We check that we are allowed to make the purchase.

        if (SKPaymentQueue.canMakePayments())
        {
            let productID:NSSet = NSSet(object: self.product_ID!);
            let productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>);
            productsRequest.delegate = self;
            productsRequest.start();
            print("Fetching Products");

        }  else { print("can't make purchases")

            let cantPurchaseAlert = UIAlertController(title: "Can't Make Purchases", message: "You do not have the ability to make purchases on this device. Please check your settings and payment info and try again.", preferredStyle: .alert)
            cantPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                self.activity.isHidden = true
                self.activity.stopAnimating()
            }))

        }

    }

    func buyProduct(_ product: SKProduct){
        print("Sending the Payment Request to Apple");
        let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment);

    }

    func productsRequest (_ request: SKProductsRequest, didReceive response: SKProductsResponse) {

        let count : Int = response.products.count
        if (count>0) {
            let validProducts = response.products
            let validProduct: SKProduct = response.products[0] as SKProduct
            if (validProduct.productIdentifier == self.product_ID as String!) {
                print(validProduct.localizedTitle)
                print(validProduct.localizedDescription)

                print(validProduct.price)
                buyProduct(validProduct);
            } else {
                print(validProduct.productIdentifier)
            }
        } else {
            print("nothing")
        }
    }

    func request(_ request: SKRequest, didFailWithError error: Error) {
        print("Error Fetching product information")

        let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@*****.com", preferredStyle: .alert)
        failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            self.activity.isHidden = true
            self.activity.stopAnimating()
        }))

        ;
    }

    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])    {
        print("Received Payment Transaction Response from Apple");

        for transaction:AnyObject in transactions {
            if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{

                switch trans.transactionState {
                case .purchased:
                    print("Product Purchased");
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)

                    subscriptionEndDate = userSettings.object(forKey: "subEnd") as? Date

                    let calendar = Calendar.current

                    let today = Date()

                    if purchaseLength == "onemonth" {

                        if (subscriptionEndDate as NSDate?)?.earlierDate(today) == today {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.month], value: 1, to: subscriptionEndDate!, options: [])!

                        } else {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.month], value: 1, to: today, options: [])!

                        } }

                    else  if purchaseLength == "oneyear" {

                        if (subscriptionEndDate as NSDate?)?.earlierDate(today) == today {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.year], value: 1, to: subscriptionEndDate!, options: [])!

                        } else {

                            subscriptionEndDate = (calendar as NSCalendar).date(byAdding: [.year], value: 1, to: today, options: [])!

                        }

                    }

                    print("added time")

                    let components = (calendar as NSCalendar).components([.day, .month, .year], from: subscriptionEndDate!)

                    let year = components.year
                    let month = components.month
                    let day = components.day

                    let testDate = "\(month!)/\(day!)/\(year!)"

                    if (subscriptionEndDate! as NSDate).laterDate(today) == subscriptionEndDate {

                        subscriptionMessageLabel.text = "Your subscription expires on:"
                        subscriptionLabel.text = "\(testDate)" }

                    else {

                        subscriptionMessageLabel.text = "There was an error in the purchase."
                        subscriptionLabel.text = "Please contact Support@UndauntedAthlete.com" }

                    userSettings.set(subscriptionEndDate, forKey: "subEnd")

                    ref.updateChildValues(["users/\(userID!)/subscriptionDate": testDate])

                    activity.isHidden = true
                    activity.stopAnimating()

                    break;

                case .failed:
                    print("Purchased Failed");
                    SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)

                    let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@****.com", preferredStyle: .alert)
                    failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                        self.activity.isHidden = true
                        self.activity.stopAnimating()
                    }))

                    break

                case .restored:
                    print("Already Purchased");
                    SKPaymentQueue.default().restoreCompletedTransactions()

                    let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@*****.com", preferredStyle: .alert)
                    failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                        self.activity.isHidden = true
                        self.activity.stopAnimating()
                    }))

                default:
                    let failedPurchaseAlert = UIAlertController(title: "We're sorry. There was an error with the purchase.", message: "Please quit the app and try again. If the error continues please email support@*****.com", preferredStyle: .alert)
                    failedPurchaseAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                        self.activity.isHidden = true
                        self.activity.stopAnimating()
                    }))

                    break
                }
            }
        }
    }